Skip to content

Commit 8abdff4

Browse files
committed
feat(unified-search): Use existing min search length config
This setting existed already for the legacy unified search. This commit expose that setting to the new front-end, and also ignore non valid requests in the backend. We also take the opportunity to register the config in the lexicon. Signed-off-by: Louis Chemineau <louis@chmn.me>
1 parent 88682d5 commit 8abdff4

7 files changed

Lines changed: 48 additions & 4 deletions

File tree

core/AppInfo/ConfigLexicon.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class ConfigLexicon implements ILexicon {
3333
public const USER_LOCALE = 'locale';
3434
public const USER_TIMEZONE = 'timezone';
3535

36+
public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length';
37+
3638
public const LASTCRON_TIMESTAMP = 'lastcron';
3739

3840
public function getStrictness(): Strictness {
@@ -90,6 +92,7 @@ public function getAppConfigs(): array {
9092
new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'),
9193
new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM', lazy: true),
9294
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'),
95+
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'),
9396
];
9497
}
9598

core/Controller/UnifiedSearchController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
2020
use OCP\AppFramework\Http\DataResponse;
2121
use OCP\AppFramework\OCSController;
22+
use OCP\IL10N;
2223
use OCP\IRequest;
2324
use OCP\IURLGenerator;
2425
use OCP\IUserSession;
@@ -37,6 +38,7 @@ public function __construct(
3738
private SearchComposer $composer,
3839
private IRouter $router,
3940
private IURLGenerator $urlGenerator,
41+
private IL10N $l10n,
4042
) {
4143
parent::__construct('core', $request);
4244
}
@@ -101,6 +103,11 @@ public function search(
101103
} catch (UnsupportedFilter|InvalidArgumentException $e) {
102104
return new DataResponse($e->getMessage(), Http::STATUS_BAD_REQUEST);
103105
}
106+
107+
if ($filters->count() === 0) {
108+
return new DataResponse($this->l10n->t('No valid filters provided'), Http::STATUS_BAD_REQUEST);
109+
}
110+
104111
return new DataResponse(
105112
$this->composer->search(
106113
$this->userSession->getUser(),

core/src/components/UnifiedSearch/UnifiedSearchModal.vue

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
181181
import NcInputField from '@nextcloud/vue/components/NcInputField'
182182
import NcDialog from '@nextcloud/vue/components/NcDialog'
183183
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
184+
import { loadState } from '@nextcloud/initial-state'
184185
185186
import CustomDateRangeModal from './CustomDateRangeModal.vue'
186187
import FilterChip from './SearchFilterChip.vue'
@@ -281,6 +282,7 @@ export default defineComponent({
281282
internalIsVisible: this.open,
282283
initialized: false,
283284
searchExternalResources: false,
285+
minSearchLength: loadState('unified-search', 'min-search-length', 1),
284286
}
285287
},
286288
@@ -293,6 +295,10 @@ export default defineComponent({
293295
return !this.isEmptySearch && this.results.length === 0
294296
},
295297
298+
isSearchQueryTooShort() {
299+
return this.searchQuery.length < this.minSearchLength
300+
},
301+
296302
showEmptyContentInfo() {
297303
return this.isEmptySearch || this.hasNoResults
298304
},
@@ -301,9 +307,16 @@ export default defineComponent({
301307
if (this.searching && this.hasNoResults) {
302308
return t('core', 'Searching …')
303309
}
304-
if (this.isEmptySearch) {
305-
return t('core', 'Start typing to search')
310+
311+
if (this.isSearchQueryTooShort) {
312+
switch (this.minSearchLength) {
313+
case 1:
314+
return t('core', 'Start typing to search')
315+
default:
316+
return t('core', 'Minimum search length is {minSearchLength} characters', { minSearchLength: this.minSearchLength })
317+
}
306318
}
319+
307320
return t('core', 'No matching results')
308321
},
309322
@@ -395,7 +408,7 @@ export default defineComponent({
395408
})
396409
},
397410
find(query: string, providersToSearchOverride = null) {
398-
if (query.length === 0) {
411+
if (this.isSearchQueryTooShort) {
399412
this.results = []
400413
this.searching = false
401414
return

lib/private/Search/FilterCollection.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ public function getIterator(): Generator {
4040
yield $k => $v;
4141
}
4242
}
43+
44+
public function count(): int {
45+
return count($this->filters);
46+
}
4347
}

lib/private/Search/SearchComposer.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
use InvalidArgumentException;
1212
use OC\AppFramework\Bootstrap\Coordinator;
13+
use OC\Core\AppInfo\Application;
14+
use OC\Core\AppInfo\ConfigLexicon;
1315
use OC\Core\ResponseDefinitions;
1416
use OCP\IAppConfig;
1517
use OCP\IURLGenerator;
@@ -315,6 +317,12 @@ private function buildFilter(string $name, string $value, string $providerId): ?
315317
throw new UnsupportedFilter($name, $providerId);
316318
}
317319

320+
$minSearchLength = $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MIN_SEARCH_LENGTH);
321+
if ($filterDefinition->name() === 'term' && mb_strlen(trim($value)) < $minSearchLength) {
322+
// Ignore term values that are not long enough
323+
return null;
324+
}
325+
318326
return FilterFactory::get($filterDefinition->type(), $value);
319327
}
320328

lib/private/TemplateLayout.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use bantu\IniGetWrapper\IniGetWrapper;
1313
use OC\AppFramework\Http\Request;
1414
use OC\Authentication\Token\IProvider;
15+
use OC\Core\AppInfo\Application;
16+
use OC\Core\AppInfo\ConfigLexicon;
1517
use OC\Files\FilenameValidator;
1618
use OC\Search\SearchQuery;
1719
use OC\Template\CSSResourceLocator;
@@ -74,9 +76,9 @@ public function getPageTemplate(string $renderAs, string $appId): ITemplate {
7476
$this->initialState->provideInitialState('core', 'active-app', $this->navigationManager->getActiveEntry());
7577
$this->initialState->provideInitialState('core', 'apps', array_values($this->navigationManager->getAll()));
7678

79+
$this->initialState->provideInitialState('unified-search', 'min-search-length', $this->appConfig->getValueInt(Application::APP_ID, ConfigLexicon::UNIFIED_SEARCH_MIN_SEARCH_LENGTH));
7780
if ($this->config->getSystemValueBool('unified_search.enabled', false) || !$this->config->getSystemValueBool('enable_non-accessible_features', true)) {
7881
$this->initialState->provideInitialState('unified-search', 'limit-default', (int)$this->config->getAppValue('core', 'unified-search.limit-default', (string)SearchQuery::LIMIT_DEFAULT));
79-
$this->initialState->provideInitialState('unified-search', 'min-search-length', (int)$this->config->getAppValue('core', 'unified-search.min-search-length', (string)1));
8082
$this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes');
8183
Util::addScript('core', 'legacy-unified-search', 'core');
8284
} else {

lib/public/Search/IFilterCollection.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ public function get(string $name): ?IFilter;
3636
* @since 28.0.0
3737
*/
3838
public function getIterator(): \Traversable;
39+
40+
/**
41+
* Return the number of filters
42+
*
43+
* @since 32.0.1
44+
*/
45+
public function count(): int;
3946
}

0 commit comments

Comments
 (0)