From 20531128871110d2aaab34db65490d583e96d006 Mon Sep 17 00:00:00 2001 From: nfebe Date: Tue, 30 Sep 2025 14:04:22 +0100 Subject: [PATCH] fix(unified-search): Remove hard-coded search result limit A change added in https://github.com/nextcloud/server/pull/45317 introduced a hard stop (25) that prevents full search results from showing up. If there are more than 25 search results for a query only 25 can be seen. So two main issues: - Only 25 results can be seen in total no matter what. - Breaks web client pagination, which typically adds 5 results per request. Signed-off-by: nfebe --- core/AppInfo/ConfigLexicon.php | 2 ++ core/Controller/UnifiedSearchController.php | 9 +++++++-- core/openapi-full.json | 2 +- core/openapi.json | 2 +- openapi.json | 2 +- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/AppInfo/ConfigLexicon.php b/core/AppInfo/ConfigLexicon.php index 4fd4eb490ba..5faa0e4a296 100644 --- a/core/AppInfo/ConfigLexicon.php +++ b/core/AppInfo/ConfigLexicon.php @@ -34,6 +34,7 @@ class ConfigLexicon implements ILexicon { public const USER_TIMEZONE = 'timezone'; public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length'; + public const UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST = 'unified_search_max_results_per_request'; public const LASTCRON_TIMESTAMP = 'lastcron'; @@ -93,6 +94,7 @@ class ConfigLexicon implements ILexicon { new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM', lazy: true), new Entry(self::OCM_INVITE_ACCEPT_DIALOG, ValueType::STRING, '', 'route to local invite accept dialog', lazy: true, note: 'set as empty string to disable feature'), new Entry(self::UNIFIED_SEARCH_MIN_SEARCH_LENGTH, ValueType::INT, 1, 'Minimum search length to trigger the request', lazy: false, rename: 'unified-search.min-search-length'), + new Entry(self::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST, ValueType::INT, 25, 'Maximum results returned per search request', lazy: false, rename: 'unified-search.max-results-per-request'), ]; } diff --git a/core/Controller/UnifiedSearchController.php b/core/Controller/UnifiedSearchController.php index 169c1f348dc..6888a9a2639 100644 --- a/core/Controller/UnifiedSearchController.php +++ b/core/Controller/UnifiedSearchController.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace OC\Core\Controller; use InvalidArgumentException; +use OC\Core\AppInfo\Application; +use OC\Core\AppInfo\ConfigLexicon; use OC\Core\ResponseDefinitions; use OC\Search\SearchComposer; use OC\Search\SearchQuery; @@ -19,6 +21,7 @@ use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; +use OCP\IAppConfig; use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; @@ -39,6 +42,7 @@ class UnifiedSearchController extends OCSController { private IRouter $router, private IURLGenerator $urlGenerator, private IL10N $l10n, + private IAppConfig $appConfig, ) { parent::__construct('core', $request); } @@ -72,7 +76,7 @@ class UnifiedSearchController extends OCSController { * @param string $providerId ID of the provider * @param string $term Term to search * @param int|null $sortOrder Order of entries - * @param int|null $limit Maximum amount of entries, limited to 25 + * @param int|null $limit Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25) * @param int|string|null $cursor Offset for searching * @param string $from The current user URL * @@ -96,7 +100,8 @@ class UnifiedSearchController extends OCSController { [$route, $routeParameters] = $this->getRouteInformation($from); $limit ??= SearchQuery::LIMIT_DEFAULT; - $limit = max(1, min($limit, 25)); + $maxLimit = $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST); + $limit = max(1, min($limit, $maxLimit)); try { $filters = $this->composer->buildFilterList($providerId, $this->request->getParams()); diff --git a/core/openapi-full.json b/core/openapi-full.json index 1cd58000816..a029ee84d9c 100644 --- a/core/openapi-full.json +++ b/core/openapi-full.json @@ -8511,7 +8511,7 @@ { "name": "limit", "in": "query", - "description": "Maximum amount of entries, limited to 25", + "description": "Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25)", "schema": { "type": "integer", "format": "int64", diff --git a/core/openapi.json b/core/openapi.json index 67b6e3fc6ce..471e6567b84 100644 --- a/core/openapi.json +++ b/core/openapi.json @@ -8511,7 +8511,7 @@ { "name": "limit", "in": "query", - "description": "Maximum amount of entries, limited to 25", + "description": "Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25)", "schema": { "type": "integer", "format": "int64", diff --git a/openapi.json b/openapi.json index 111c5650c61..8307e44dda7 100644 --- a/openapi.json +++ b/openapi.json @@ -12024,7 +12024,7 @@ { "name": "limit", "in": "query", - "description": "Maximum amount of entries, limited to 25", + "description": "Maximum amount of entries (capped by configurable unified-search.max-results-per-request, default: 25)", "schema": { "type": "integer", "format": "int64",