Sfoglia il codice sorgente

Filter by multiple feed IDs (#2892)

Add the possibility to filter by feed ID like `f:123 more-search`
or multiple feed IDs, like `f:123,234,345 more-search` or an exclusion
like `!f:456,789 more-search`
Alexandre Alapetite 6 anni fa
parent
commit
ae70374b03

+ 20 - 0
app/Models/EntryDAO.php

@@ -703,6 +703,26 @@ SQL;
 					continue;
 				}
 				$sub_search = '';
+
+				if ($filter->getFeedIds()) {
+					$sub_search .= 'AND ' . $alias . 'id_feed IN (';
+					foreach ($filter->getFeedIds() as $feed_id) {
+						$sub_search .= '?,';
+						$values[] = $feed_id;
+					}
+					$sub_search = rtrim($sub_search, ',');
+					$sub_search .= ') ';
+				}
+				if ($filter->getNotFeedIds()) {
+					$sub_search .= 'AND ' . $alias . 'id_feed NOT IN (';
+					foreach ($filter->getNotFeedIds() as $feed_id) {
+						$sub_search .= '?,';
+						$values[] = $feed_id;
+					}
+					$sub_search = rtrim($sub_search, ',');
+					$sub_search .= ') ';
+				}
+
 				if ($filter->getMinDate()) {
 					$sub_search .= 'AND ' . $alias . 'id >= ? ';
 					$values[] = "{$filter->getMinDate()}000000";

+ 46 - 0
app/Models/Search.php

@@ -12,7 +12,9 @@ class FreshRSS_Search {
 
 	// This contains the user input string
 	private $raw_input = '';
+
 	// The following properties are extracted from the raw input
+	private $feed_ids;
 	private $intitle;
 	private $min_date;
 	private $max_date;
@@ -23,6 +25,7 @@ class FreshRSS_Search {
 	private $tags;
 	private $search;
 
+	private $not_feed_ids;
 	private $not_intitle;
 	private $not_min_date;
 	private $not_max_date;
@@ -41,6 +44,8 @@ class FreshRSS_Search {
 
 		$input = preg_replace('/:"(.*?)"/', ':"\1"', $input);
 
+		$input = $this->parseNotFeedIds($input);
+
 		$input = $this->parseNotPubdateSearch($input);
 		$input = $this->parseNotDateSearch($input);
 
@@ -49,6 +54,8 @@ class FreshRSS_Search {
 		$input = $this->parseNotInurlSearch($input);
 		$input = $this->parseNotTagsSearch($input);
 
+		$input = $this->parseFeedIds($input);
+
 		$input = $this->parsePubdateSearch($input);
 		$input = $this->parseDateSearch($input);
 
@@ -69,6 +76,13 @@ class FreshRSS_Search {
 		return $this->raw_input;
 	}
 
+	public function getFeedIds() {
+		return $this->feed_ids;
+	}
+	public function getNotFeedIds() {
+		return $this->not_feed_ids;
+	}
+
 	public function getIntitle() {
 		return $this->intitle;
 	}
@@ -153,6 +167,38 @@ class FreshRSS_Search {
 		return $value;
 	}
 
+	/**
+	 * Parse the search string to find feed IDs.
+	 *
+	 * @param string $input
+	 * @return string
+	 */
+	private function parseFeedIds($input) {
+		if (preg_match_all('/\bf:(?P<search>[0-9,]*)/', $input, $matches)) {
+			$ids_lists = $matches['search'];
+			$input = str_replace($matches[0], '', $input);
+			$ids_lists = self::removeEmptyValues($ids_lists);
+			if (!empty($ids_lists[0])) {
+				$this->feed_ids = explode(',', $ids_lists[0]);
+				array_filter($this->feed_ids, function($v) { $v != ''; });
+			}
+		}
+		return $input;
+	}
+
+	private function parseNotFeedIds($input) {
+		if (preg_match_all('/[!-]f:(?P<search>[0-9,]*)/', $input, $matches)) {
+			$ids_lists = $matches['search'];
+			$input = str_replace($matches[0], '', $input);
+			$ids_lists = self::removeEmptyValues($ids_lists);
+			if (!empty($ids_lists[0])) {
+				$this->not_feed_ids = explode(',', $ids_lists[0]);
+				array_filter($this->not_feed_ids, function($v) { $v != ''; });
+			}
+		}
+		return $input;
+	}
+
 	/**
 	 * Parse the search string to find intitle keyword and the search related
 	 * to it.

+ 6 - 4
docs/en/users/03_Main_view.md

@@ -158,6 +158,7 @@ It is possible to filter articles by their content by inputting a string in the
 
 You can use the search field to further refine results:
 
+* by feed ID: `f:123` or multiple feed IDs: `f:123,234,345`
 * by author: `author:name` or `author:'composed name'`
 * by title: `intitle:keyword` or `intitle:'composed keyword'`
 * by URL: `inurl:keyword` or `inurl:'composed keyword'`
@@ -200,9 +201,10 @@ You can use the search field to further refine results:
 Be careful not to enter a space between the operator and the search value.
 
 Some operators can be used negatively, to exclude articles, with the same syntax as above, but prefixed by a `!` or `-`:
-`-author:name`, `-intitle:keyword`, `-inurl:keyword`, `-#tag`, `!keyword`, `!date:2019`, `!date:P1W`, `!pubdate:P3d/`.
+`!f:234`, `-author:name`, `-intitle:keyword`, `-inurl:keyword`, `-#tag`, `!keyword`, `!date:2019`, `!date:P1W`, `!pubdate:P3d/`.
 
-It is also possible to combine keywords to create a more precise filter. For example, you can enter multiple instances of `author:`, `intitle:`, `inurl:`, `#`, and free-text.
+It is also possible to combine keywords to create a more precise filter.
+For example, you can enter multiple instances of `f:`, `author:`, `intitle:`, `inurl:`, `#`, and free-text.
 
-Combining several search criteria implies a logical *and*, but the keyword ` OR ` can be used to combine several search criteria with a logical *or* instead:
-`author:Dupont OR author:Dupond`
+Combining several search criteria implies a logical *and*, but the keyword ` OR `
+can be used to combine several search criteria with a logical *or* instead: `author:Dupont OR author:Dupond`

+ 7 - 7
docs/fr/users/03_Main_view.md

@@ -207,6 +207,7 @@ the search field.
 Il est possible d’utiliser le champ de recherche pour raffiner les résultats
 :
 
+* par ID de flux : `f:123` ou plusieurs flux : `f:123,234,345`
 * par auteur : `author:nom` or `author:'nom composé'`
 * par titre : `intitle:mot` or `intitle:'mot composé'`
 * par URL: `inurl:mot` or `inurl:'mot composé'`
@@ -244,19 +245,18 @@ Il est possible d’utiliser le champ de recherche pour raffiner les résultats
 		* `date:PT30M/` (past thirty minutes)
 		* `date:PT90S/` (past ninety seconds)
 		* `date:P1DT1H/` (past one day and one hour)
-* by date of publication, using the same format: `pubdate:<date-interval>`
+* par date de publication, avec la même syntaxe: `pubdate:<date-interval>`
 
 Attention à ne pas introduire d’espace entre l’opérateur et la valeur
 recherchée.
 
 Certains opérateurs peuvent être utilisé négativement, pour exclure des
-articles, avec la même syntaxe que ci-dessus, mais préfixé par `!` ou `-`
-:`-author:nom`, `-intitle:mot`, `-inurl:mot`, `-#tag`, `!mot`, `!date:2019`, `!date:P1W`, `!pubdate:P3d/`.
+articles, avec la même syntaxe que ci-dessus, mais préfixé par `!` ou `-` :
+`!f:123`, `-author:nom`, `-intitle:mot`, `-inurl:mot`, `-#tag`, `!mot`, `!date:2019`, `!date:P1W`, `!pubdate:P3d/`.
 
 Il est également possible de combiner les mots-clefs pour faire un filtrage
 encore plus précis, et il est autorisé d’avoir plusieurs instances de :
-`author:`, `intitle:`, `inurl:`, `#`, et texte libre.
+`f:`, `author:`, `intitle:`, `inurl:`, `#`, et texte libre.
 
-Combiner plusieurs critères implique un *et* logique, mais le mot clef ` OR
-` peut être utiliser pour combiner plusieurs critères avec un *ou* logique
-:`author:Dupont OR author:Dupond`
+Combiner plusieurs critères implique un *et* logique, mais le mot clef ` OR`
+peut être utiliser pour combiner plusieurs critères avec un *ou* logique : `author:Dupont OR author:Dupond`