Skip to content

Commit 979e231

Browse files
committed
fix: make user search case-insensitive across all supported databases
MySQL/MariaDB already handles this via collation (LIKE), PostgreSQL now uses ILIKE, and SQLite uses LOWER(username) LIKE since its LIKE is only ASCII case-insensitive. Applies to both FulltextFilter (API/user directory search) and UserRepository::getIdsForUsername (mention autocomplete etc).
1 parent 9fff5dc commit 979e231

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

framework/core/src/User/Search/FulltextFilter.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,38 @@ public function __construct(
2626
) {
2727
}
2828

29+
public function search(SearchState $state, string $value): void
30+
{
31+
$state->getQuery()
32+
->whereIn(
33+
'id',
34+
match ($state->getQuery()->getConnection()->getDriverName()) {
35+
'pgsql' => $this->getUserSearchSubQuery($value, 'ilike'),
36+
'sqlite' => $this->getUserSearchSubQueryLower($value),
37+
default => $this->getUserSearchSubQuery($value, 'like'),
38+
}
39+
);
40+
}
41+
2942
/**
3043
* @return Builder<User>
3144
*/
32-
private function getUserSearchSubQuery(string $searchValue): Builder
45+
private function getUserSearchSubQuery(string $searchValue, string $operator): Builder
3346
{
3447
return $this->users
3548
->query()
3649
->select('id')
37-
->where('username', 'like', "$searchValue%");
50+
->where('username', $operator, "$searchValue%");
3851
}
3952

40-
public function search(SearchState $state, string $value): void
53+
/**
54+
* @return Builder<User>
55+
*/
56+
private function getUserSearchSubQueryLower(string $searchValue): Builder
4157
{
42-
$state->getQuery()
43-
->whereIn(
44-
'id',
45-
$this->getUserSearchSubQuery($value)
46-
);
58+
return $this->users
59+
->query()
60+
->select('id')
61+
->whereRaw('LOWER(username) LIKE ?', [strtolower($searchValue).'%']);
4762
}
4863
}

framework/core/src/User/UserRepository.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,22 @@ public function getIdsForUsername(string $string, ?User $actor = null): array
9797
{
9898
$string = $this->escapeLikeString($string);
9999

100-
$query = $this->query()->where('username', 'like', '%'.$string.'%')
101-
->orderByRaw('username = ? desc', [$string])
102-
->orderByRaw('username like ? desc', [$string.'%']);
100+
$query = $this->query();
101+
102+
match ($query->getConnection()->getDriverName()) {
103+
'pgsql' => $query
104+
->where('username', 'ilike', '%'.$string.'%')
105+
->orderByRaw('username = ? desc', [$string])
106+
->orderByRaw('username ilike ? desc', [$string.'%']),
107+
'sqlite' => $query
108+
->whereRaw('LOWER(username) LIKE ?', ['%'.strtolower($string).'%'])
109+
->orderByRaw('LOWER(username) = ? desc', [strtolower($string)])
110+
->orderByRaw('LOWER(username) LIKE ? desc', [strtolower($string).'%']),
111+
default => $query
112+
->where('username', 'like', '%'.$string.'%')
113+
->orderByRaw('username = ? desc', [$string])
114+
->orderByRaw('username like ? desc', [$string.'%']),
115+
};
103116

104117
return $this->scopeVisibleTo($query, $actor)->pluck('id')->all();
105118
}

0 commit comments

Comments
 (0)