diff options
| author | 2026-01-10 19:14:26 +0100 | |
|---|---|---|
| committer | 2026-01-10 19:14:26 +0100 | |
| commit | b0a5f063abcc021644ecaf4d5cefbd2c7dd276ec (patch) | |
| tree | 25a102b6ce4648a4439cd7f0aa6474d9d075c1fd /app | |
| parent | 6b46e70f5a7218943b5178939ed3335a96b22dfc (diff) | |
Fix tags ILIKE (#8425)
fix https://github.com/FreshRSS/FreshRSS/issues/8424
Regression from https://github.com/FreshRSS/FreshRSS/issues/8329
Diffstat (limited to 'app')
| -rw-r--r-- | app/Models/DatabaseDAO.php | 6 | ||||
| -rw-r--r-- | app/Models/DatabaseDAOPGSQL.php | 9 | ||||
| -rw-r--r-- | app/Models/DatabaseDAOSQLite.php | 4 | ||||
| -rw-r--r-- | app/Models/Entry.php | 20 |
4 files changed, 21 insertions, 18 deletions
diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index 3d8389c87..e419e5892 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -504,11 +504,13 @@ SQL; /** * PHP emulation of the SQL ILIKE operation of the selected database. * 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. $haystack = self::removeAccentsLower($haystack); $needle = self::removeAccentsLower($needle); - return str_contains($haystack, $needle); + return $contains ? str_contains($haystack, $needle) : ($haystack === $needle); } } diff --git a/app/Models/DatabaseDAOPGSQL.php b/app/Models/DatabaseDAOPGSQL.php index 116f8816e..1ead69192 100644 --- a/app/Models/DatabaseDAOPGSQL.php +++ b/app/Models/DatabaseDAOPGSQL.php @@ -101,17 +101,18 @@ SQL; } #[\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')) { - 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')) { $haystack_ = transliterator_transliterate('Lower', $haystack); $needle_ = transliterator_transliterate('Lower', $needle); 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); } } diff --git a/app/Models/DatabaseDAOSQLite.php b/app/Models/DatabaseDAOSQLite.php index 9a4842c39..661c669dc 100644 --- a/app/Models/DatabaseDAOSQLite.php +++ b/app/Models/DatabaseDAOSQLite.php @@ -101,7 +101,7 @@ class FreshRSS_DatabaseDAOSQLite extends FreshRSS_DatabaseDAO { } #[\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); } } diff --git a/app/Models/Entry.php b/app/Models/Entry.php index 0fb82a203..146423fd2 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -699,7 +699,7 @@ HTML; } if ($ok && $filter->getAuthor() !== null) { 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) { @@ -709,7 +709,7 @@ HTML; } if ($ok && $filter->getNotAuthor() !== null) { 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) { @@ -719,7 +719,7 @@ HTML; } if ($ok && $filter->getIntitle() !== null) { foreach ($filter->getIntitle() as $title) { - $ok &= $databaseDao::strilike($this->title, $title); + $ok &= $databaseDao::strilike($this->title, $title, contains: true); } } if ($ok && $filter->getIntitleRegex() !== null) { @@ -729,7 +729,7 @@ HTML; } if ($ok && $filter->getNotIntitle() !== null) { foreach ($filter->getNotIntitle() as $title) { - $ok &= !$databaseDao::strilike($this->title, $title); + $ok &= !$databaseDao::strilike($this->title, $title, contains: true); } } if ($ok && $filter->getNotIntitleRegex() !== null) { @@ -739,7 +739,7 @@ HTML; } if ($ok && $filter->getIntext() !== null) { foreach ($filter->getIntext() as $content) { - $ok &= $databaseDao::strilike($this->content, $content); + $ok &= $databaseDao::strilike($this->content, $content, contains: true); } } if ($ok && $filter->getIntextRegex() !== null) { @@ -749,7 +749,7 @@ HTML; } if ($ok && $filter->getNotIntext() !== null) { foreach ($filter->getNotIntext() as $content) { - $ok &= !$databaseDao::strilike($this->content, $content); + $ok &= !$databaseDao::strilike($this->content, $content, contains: true); } } if ($ok && $filter->getNotIntextRegex() !== null) { @@ -762,7 +762,7 @@ HTML; $found = false; foreach ($this->tags as $tag1) { $tag1 = ltrim($tag1, '#'); - if ($databaseDao::strilike($tag1, $tag2)) { + if ($databaseDao::strilike($tag1, $tag2, contains: false)) { $found = true; break; } @@ -788,7 +788,7 @@ HTML; $found = false; foreach ($this->tags as $tag1) { $tag1 = ltrim($tag1, '#'); - if ($databaseDao::strilike($tag1, $tag2)) { + if ($databaseDao::strilike($tag1, $tag2, contains: false)) { $found = true; break; } @@ -831,12 +831,12 @@ HTML; } if ($ok && $filter->getSearch() !== null) { 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) { 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) { |
