From e070c3ed2bec4ea4a6c2a216a5c836d1e02ab381 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 15 Oct 2025 00:08:40 +0200 Subject: Implement search form (#8103) * Add UI for advanced search To help users with the seach operators. Obviously not as powerful as a manually-written search query. Lack in particular negation and logical *and* for now, but I might try to do something about it. image * Consistency: allow multiple user queries like S:1,2 * Fix user query and add tests --- tests/app/Models/SearchTest.php | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'tests/app') diff --git a/tests/app/Models/SearchTest.php b/tests/app/Models/SearchTest.php index 4c66880db..19279fa65 100644 --- a/tests/app/Models/SearchTest.php +++ b/tests/app/Models/SearchTest.php @@ -224,6 +224,70 @@ final class SearchTest extends \PHPUnit\Framework\TestCase { ]; } + /** + * @param list $queries + * @param array{0:string,1:list} $expectedResult + */ + #[DataProvider('provideSavedQueryIdExpansion')] + public static function test__construct_whenInputContainsSavedQueryIds_expandsSavedSearches(array $queries, string $input, array $expectedResult): void { + $previousUserConf = FreshRSS_Context::hasUserConf() ? FreshRSS_Context::userConf() : null; + $newUserConf = $previousUserConf instanceof FreshRSS_UserConfiguration ? clone $previousUserConf : clone FreshRSS_UserConfiguration::default(); + $newUserConf->queries = $queries; + FreshRSS_Context::$user_conf = $newUserConf; + + try { + $search = new FreshRSS_BooleanSearch($input); + [$actualValues, $actualSql] = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', $search); + self::assertSame($expectedResult[0], trim($actualSql)); + self::assertSame($expectedResult[1], $actualValues); + } finally { + FreshRSS_Context::$user_conf = $previousUserConf; + } + } + + /** + * @return array,1:string,2:array{0:string,1:list}}> + */ + public static function provideSavedQueryIdExpansion(): array { + return [ + 'expanded single group' => [ + [ + ['search' => 'author:Alice'], + ['search' => 'intitle:World'], + ], + 'S:0,1', + [ + '((e.author LIKE ? )) OR ((e.title LIKE ? ))', + ['%Alice%', '%World%'], + ], + ], + 'separate groups with OR' => [ + [ + ['search' => 'author:Alice'], + ['search' => 'intitle:World'], + ['search' => 'inurl:Example'], + ['search' => 'author:Bob'], + ], + 'S:0,1 OR S:2,3', + [ + '((e.author LIKE ? )) OR ((e.title LIKE ? )) OR ((e.link LIKE ? )) OR ((e.author LIKE ? ))', + ['%Alice%', '%World%', '%Example%', '%Bob%'], + ], + ], + 'mixed with other clauses' => [ + [ + ['search' => 'author:Alice'], + ['search' => 'intitle:World'], + ], + 'intitle:Hello S:0,1 date:2025-10', + [ + '((e.title LIKE ? )) AND ((e.author LIKE ? )) OR ((e.title LIKE ? )) AND ((e.id >= ? AND e.id <= ? ))', + ['%Hello%', '%Alice%', '%World%', strtotime('2025-10-01') . '000000', (strtotime('2025-11-01') - 1) . '000000'], + ], + ], + ]; + } + /** * @param array|null $author_value * @param array $intitle_value -- cgit v1.2.3