Просмотр исходного кода

Search on article IDs (#4058)

* Search on article IDs
Partial implementation of https://github.com/FreshRSS/FreshRSS/issues/4053
Alexandre Alapetite 4 лет назад
Родитель
Сommit
fb15a2d804
4 измененных файлов с 74 добавлено и 0 удалено
  1. 23 0
      app/Models/EntryDAO.php
  2. 49 0
      app/Models/Search.php
  3. 1 0
      docs/en/users/03_Main_view.md
  4. 1 0
      docs/fr/users/03_Main_view.md

+ 23 - 0
app/Models/EntryDAO.php

@@ -732,6 +732,29 @@ SQL;
 				}
 				$sub_search = '';
 
+				if ($filter->getEntryIds()) {
+					foreach ($filter->getEntryIds() as $entry_ids) {
+						$sub_search .= 'AND ' . $alias . 'id IN (';
+						foreach ($entry_ids as $entry_id) {
+							$sub_search .= '?,';
+							$values[] = $entry_id;
+						}
+						$sub_search = rtrim($sub_search, ',');
+						$sub_search .= ') ';
+					}
+				}
+				if ($filter->getNotEntryIds()) {
+					foreach ($filter->getNotEntryIds() as $entry_ids) {
+						$sub_search .= 'AND ' . $alias . 'id NOT IN (';
+						foreach ($entry_ids as $entry_id) {
+							$sub_search .= '?,';
+							$values[] = $entry_id;
+						}
+						$sub_search = rtrim($sub_search, ',');
+						$sub_search .= ') ';
+					}
+				}
+
 				if ($filter->getMinDate()) {
 					$sub_search .= 'AND ' . $alias . 'id >= ? ';
 					$values[] = "{$filter->getMinDate()}000000";

+ 49 - 0
app/Models/Search.php

@@ -14,6 +14,7 @@ class FreshRSS_Search {
 	private $raw_input = '';
 
 	// The following properties are extracted from the raw input
+	private $entry_ids;
 	private $feed_ids;
 	private $label_ids;
 	private $label_names;
@@ -27,6 +28,7 @@ class FreshRSS_Search {
 	private $tags;
 	private $search;
 
+	private $not_entry_ids;
 	private $not_feed_ids;
 	private $not_label_ids;
 	private $not_label_names;
@@ -48,6 +50,7 @@ class FreshRSS_Search {
 
 		$input = preg_replace('/:"(.*?)"/', ':"\1"', $input);
 
+		$input = $this->parseNotEntryIds($input);
 		$input = $this->parseNotFeedIds($input);
 		$input = $this->parseNotLabelIds($input);
 		$input = $this->parseNotLabelNames($input);
@@ -60,6 +63,7 @@ class FreshRSS_Search {
 		$input = $this->parseNotInurlSearch($input);
 		$input = $this->parseNotTagsSearch($input);
 
+		$input = $this->parseEntryIds($input);
 		$input = $this->parseFeedIds($input);
 		$input = $this->parseLabelIds($input);
 		$input = $this->parseLabelNames($input);
@@ -84,6 +88,13 @@ class FreshRSS_Search {
 		return $this->raw_input;
 	}
 
+	public function getEntryIds() {
+		return $this->entry_ids;
+	}
+	public function getNotEntryIds() {
+		return $this->not_entry_ids;
+	}
+
 	public function getFeedIds() {
 		return $this->feed_ids;
 	}
@@ -188,6 +199,44 @@ class FreshRSS_Search {
 		return $value;
 	}
 
+	/**
+	 * Parse the search string to find entry (article) IDs.
+	 *
+	 * @param string $input
+	 * @return string
+	 */
+	private function parseEntryIds($input) {
+		if (preg_match_all('/\be:(?P<search>[0-9,]*)/', $input, $matches)) {
+			$input = str_replace($matches[0], '', $input);
+			$ids_lists = $matches['search'];
+			$this->entry_ids = [];
+			foreach ($ids_lists as $ids_list) {
+				$entry_ids = explode(',', $ids_list);
+				$entry_ids = self::removeEmptyValues($entry_ids);
+				if (!empty($entry_ids)) {
+					$this->entry_ids[] = $entry_ids;
+				}
+			}
+		}
+		return $input;
+	}
+
+	private function parseNotEntryIds($input) {
+		if (preg_match_all('/[!-]e:(?P<search>[0-9,]*)/', $input, $matches)) {
+			$input = str_replace($matches[0], '', $input);
+			$ids_lists = $matches['search'];
+			$this->not_entry_ids = [];
+			foreach ($ids_lists as $ids_list) {
+				$entry_ids = explode(',', $ids_list);
+				$entry_ids = self::removeEmptyValues($entry_ids);
+				if (!empty($entry_ids)) {
+					$this->not_entry_ids[] = $entry_ids;
+				}
+			}
+		}
+		return $input;
+	}
+
 	/**
 	 * Parse the search string to find feed IDs.
 	 *

+ 1 - 0
docs/en/users/03_Main_view.md

@@ -227,6 +227,7 @@ You can use the search field to further refine results:
 * by custom label ID `L:12` or multiple label IDs: `L:12,13,14` or with any label: `L:*`
 * by custom label name `label:label`, `label:"my label"` or any label name from a list (*or*): `labels:"my label,my other label"`
 * by several label names (*and*): `label:"my label" label:"my other label"`
+* by entry (article) ID: `e:1639310674957894` or multiple entry IDs  (*or*): `e:1639310674957894,1639310674957893`
 
 Be careful not to enter a space between the operator and the search value.
 

+ 1 - 0
docs/fr/users/03_Main_view.md

@@ -251,6 +251,7 @@ Il est possible d’utiliser le champ de recherche pour raffiner les résultats
 * par ID d’étiquette : `L:12` ou de plusieurs étiquettes : `L:12,13,14` ou avec n’importe quelle étiquette : `L:*`
 * par nom d’étiquette : `label:étiquette`, `label:"mon étiquette"` ou d’une étiquette parmis une liste (*ou*) : `labels:"mon étiquette,mon autre étiquette"`
 * par plusieurs noms d’étiquettes (*et*) : `label:"mon étiquette" label:"mon autre étiquette"`
+* par ID d’article (entrée) : `e:1639310674957894` ou de plusieurs articles (*ou*): `e:1639310674957894,1639310674957893`
 
 Attention à ne pas introduire d’espace entre l’opérateur et la valeur
 recherchée.