1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Libraries\Search;
7
8use App\Libraries\Elasticsearch\BoolQuery;
9use App\Libraries\Elasticsearch\RecordSearch;
10use App\Models\User;
11use App\Transformers\UserCompactTransformer;
12
13class UserSearch extends RecordSearch
14{
15 public function __construct(?UserSearchParams $params = null)
16 {
17 parent::__construct(
18 User::esIndexName(),
19 $params ?? new UserSearchParams(),
20 User::class
21 );
22 }
23
24 public function records()
25 {
26 return $this->response()->records()->with(UserCompactTransformer::CARD_INCLUDES_PRELOAD)->get();
27 }
28
29 /**
30 * {@inheritdoc}
31 */
32 public function getQuery()
33 {
34 static $lowercase_stick = [
35 'analyzer' => 'username_lower',
36 'type' => 'most_fields',
37 'fields' => ['username', 'username._*'],
38 ];
39
40 static $whitespace_stick = [
41 'analyzer' => 'whitespace',
42 'type' => 'most_fields',
43 'fields' => ['username', 'username._*'],
44 ];
45
46 $query = (new BoolQuery())
47 ->mustNot(['terms' => ['_id' => $this->params->blockedUserIds()]])
48 ->mustNot(['term' => ['is_old' => true]])
49 ->filter(['term' => ['user_warnings' => 0]])
50 ->filter(['term' => ['user_type' => 0]]);
51
52 if ($this->params->queryString !== null) {
53 $query->shouldMatch(1)
54 ->should(['term' => ['_id' => ['value' => $this->params->queryString, 'boost' => 100]]])
55 ->should(['match' => ['username.raw' => ['query' => $this->params->queryString, 'boost' => 5]]])
56 ->should(['match' => ['previous_usernames' => ['query' => $this->params->queryString]]])
57 ->should(['multi_match' => array_merge(['query' => $this->params->queryString], $lowercase_stick)])
58 ->should(['multi_match' => array_merge(['query' => $this->params->queryString], $whitespace_stick)])
59 ->should(['match_phrase' => ['username._slop' => $this->params->queryString]]);
60 }
61
62 if ($this->params->recentOnly) {
63 $query->filter([
64 'range' => [
65 'user_lastvisit' => [
66 'gte' => 'now-90d',
67 ],
68 ],
69 ]);
70 }
71
72 return $query;
73 }
74
75 protected function maxResults(): int
76 {
77 return $GLOBALS['cfg']['osu']['search']['max']['user'];
78 }
79}