Explorar o código

Fix tags ILIKE (#8425)

fix https://github.com/FreshRSS/FreshRSS/issues/8424
Regression from https://github.com/FreshRSS/FreshRSS/issues/8329
Alexandre Alapetite hai 2 meses
pai
achega
b0a5f063ab

+ 4 - 2
app/Models/DatabaseDAO.php

@@ -504,11 +504,13 @@ SQL;
 	/**
 	/**
 	 * PHP emulation of the SQL ILIKE operation of the selected database.
 	 * PHP emulation of the SQL ILIKE operation of the selected database.
 	 * Note that it depends on the database collation settings and Unicode extensions.
 	 * Note that it depends on the database collation settings and Unicode extensions.
+	 * @param bool $contains If true, checks whether $haystack contains $needle (`'Testing' ILIKE '%Test%'`),
+	 *  otherwise checks whether they are alike (`'Testing' ILIKE 'Test'`).
 	 */
 	 */
-	public static function strilike(string $haystack, string $needle): bool {
+	public static function strilike(string $haystack, string $needle, bool $contains = false): bool {
 		// Implementation approximating MySQL/MariaDB `LIKE` with `utf8mb4_unicode_ci` collation.
 		// Implementation approximating MySQL/MariaDB `LIKE` with `utf8mb4_unicode_ci` collation.
 		$haystack = self::removeAccentsLower($haystack);
 		$haystack = self::removeAccentsLower($haystack);
 		$needle = self::removeAccentsLower($needle);
 		$needle = self::removeAccentsLower($needle);
-		return str_contains($haystack, $needle);
+		return $contains ? str_contains($haystack, $needle) : ($haystack === $needle);
 	}
 	}
 }
 }

+ 5 - 4
app/Models/DatabaseDAOPGSQL.php

@@ -101,17 +101,18 @@ SQL;
 	}
 	}
 
 
 	#[\Override]
 	#[\Override]
-	public static function strilike(string $haystack, string $needle): bool {
+	public static function strilike(string $haystack, string $needle, bool $contains = false): bool {
 		if (function_exists('mb_stripos')) {
 		if (function_exists('mb_stripos')) {
-			return mb_stripos($haystack, $needle, 0, 'UTF-8') !== false;
+			return $contains ? (mb_stripos($haystack, $needle, 0, 'UTF-8') !== false) :
+				(mb_strtolower($haystack, 'UTF-8') === mb_strtolower($needle, 'UTF-8'));
 		}
 		}
 		if (function_exists('transliterator_transliterate')) {
 		if (function_exists('transliterator_transliterate')) {
 			$haystack_ = transliterator_transliterate('Lower', $haystack);
 			$haystack_ = transliterator_transliterate('Lower', $haystack);
 			$needle_ = transliterator_transliterate('Lower', $needle);
 			$needle_ = transliterator_transliterate('Lower', $needle);
 			if ($haystack_ !== false && $needle_ !== false) {
 			if ($haystack_ !== false && $needle_ !== false) {
-				return str_contains($haystack_, $needle_);
+				return $contains ? str_contains($haystack_, $needle_) : ($haystack_ === $needle_);
 			}
 			}
 		}
 		}
-		return stripos($haystack, $needle) !== false;
+		return $contains ? (stripos($haystack, $needle) !== false) : (strcasecmp($haystack, $needle) === 0);
 	}
 	}
 }
 }

+ 2 - 2
app/Models/DatabaseDAOSQLite.php

@@ -101,7 +101,7 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO {
 	}
 	}
 
 
 	#[\Override]
 	#[\Override]
-	public static function strilike(string $haystack, string $needle): bool {
-		return stripos($haystack, $needle) !== false;
+	public static function strilike(string $haystack, string $needle, bool $contains = false): bool {
+		return $contains ? (stripos($haystack, $needle) !== false) : (strcasecmp($haystack, $needle) === 0);
 	}
 	}
 }
 }

+ 10 - 10
app/Models/Entry.php

@@ -699,7 +699,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getAuthor() !== null) {
 				if ($ok && $filter->getAuthor() !== null) {
 					foreach ($filter->getAuthor() as $author) {
 					foreach ($filter->getAuthor() as $author) {
-						$ok &= $databaseDao::strilike(implode(';', $this->authors), $author);
+						$ok &= $databaseDao::strilike(implode(';', $this->authors), $author, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getAuthorRegex() !== null) {
 				if ($ok && $filter->getAuthorRegex() !== null) {
@@ -709,7 +709,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getNotAuthor() !== null) {
 				if ($ok && $filter->getNotAuthor() !== null) {
 					foreach ($filter->getNotAuthor() as $author) {
 					foreach ($filter->getNotAuthor() as $author) {
-						$ok &= !$databaseDao::strilike(implode(';', $this->authors), $author);
+						$ok &= !$databaseDao::strilike(implode(';', $this->authors), $author, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getNotAuthorRegex() !== null) {
 				if ($ok && $filter->getNotAuthorRegex() !== null) {
@@ -719,7 +719,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getIntitle() !== null) {
 				if ($ok && $filter->getIntitle() !== null) {
 					foreach ($filter->getIntitle() as $title) {
 					foreach ($filter->getIntitle() as $title) {
-						$ok &= $databaseDao::strilike($this->title, $title);
+						$ok &= $databaseDao::strilike($this->title, $title, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getIntitleRegex() !== null) {
 				if ($ok && $filter->getIntitleRegex() !== null) {
@@ -729,7 +729,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getNotIntitle() !== null) {
 				if ($ok && $filter->getNotIntitle() !== null) {
 					foreach ($filter->getNotIntitle() as $title) {
 					foreach ($filter->getNotIntitle() as $title) {
-						$ok &= !$databaseDao::strilike($this->title, $title);
+						$ok &= !$databaseDao::strilike($this->title, $title, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getNotIntitleRegex() !== null) {
 				if ($ok && $filter->getNotIntitleRegex() !== null) {
@@ -739,7 +739,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getIntext() !== null) {
 				if ($ok && $filter->getIntext() !== null) {
 					foreach ($filter->getIntext() as $content) {
 					foreach ($filter->getIntext() as $content) {
-						$ok &= $databaseDao::strilike($this->content, $content);
+						$ok &= $databaseDao::strilike($this->content, $content, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getIntextRegex() !== null) {
 				if ($ok && $filter->getIntextRegex() !== null) {
@@ -749,7 +749,7 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getNotIntext() !== null) {
 				if ($ok && $filter->getNotIntext() !== null) {
 					foreach ($filter->getNotIntext() as $content) {
 					foreach ($filter->getNotIntext() as $content) {
-						$ok &= !$databaseDao::strilike($this->content, $content);
+						$ok &= !$databaseDao::strilike($this->content, $content, contains: true);
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getNotIntextRegex() !== null) {
 				if ($ok && $filter->getNotIntextRegex() !== null) {
@@ -762,7 +762,7 @@ HTML;
 						$found = false;
 						$found = false;
 						foreach ($this->tags as $tag1) {
 						foreach ($this->tags as $tag1) {
 							$tag1 = ltrim($tag1, '#');
 							$tag1 = ltrim($tag1, '#');
-							if ($databaseDao::strilike($tag1, $tag2)) {
+							if ($databaseDao::strilike($tag1, $tag2, contains: false)) {
 								$found = true;
 								$found = true;
 								break;
 								break;
 							}
 							}
@@ -788,7 +788,7 @@ HTML;
 						$found = false;
 						$found = false;
 						foreach ($this->tags as $tag1) {
 						foreach ($this->tags as $tag1) {
 							$tag1 = ltrim($tag1, '#');
 							$tag1 = ltrim($tag1, '#');
-							if ($databaseDao::strilike($tag1, $tag2)) {
+							if ($databaseDao::strilike($tag1, $tag2, contains: false)) {
 								$found = true;
 								$found = true;
 								break;
 								break;
 							}
 							}
@@ -831,12 +831,12 @@ HTML;
 				}
 				}
 				if ($ok && $filter->getSearch() !== null) {
 				if ($ok && $filter->getSearch() !== null) {
 					foreach ($filter->getSearch() as $needle) {
 					foreach ($filter->getSearch() as $needle) {
-						$ok &= ($databaseDao::strilike($this->title, $needle) || $databaseDao::strilike($this->content, $needle));
+						$ok &= ($databaseDao::strilike($this->title, $needle, contains: true) || $databaseDao::strilike($this->content, $needle, contains: true));
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getNotSearch() !== null) {
 				if ($ok && $filter->getNotSearch() !== null) {
 					foreach ($filter->getNotSearch() as $needle) {
 					foreach ($filter->getNotSearch() as $needle) {
-						$ok &= (!$databaseDao::strilike($this->title, $needle) && !$databaseDao::strilike($this->content, $needle));
+						$ok &= (!$databaseDao::strilike($this->title, $needle, contains: true) && !$databaseDao::strilike($this->content, $needle, contains: true));
 					}
 					}
 				}
 				}
 				if ($ok && $filter->getSearchRegex() !== null) {
 				if ($ok && $filter->getSearchRegex() !== null) {