the browser-facing portion of osu!
at master 107 lines 3.3 kB view raw
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\Highlight; 10use App\Libraries\Elasticsearch\Hit; 11use App\Libraries\Elasticsearch\QueryHelper; 12use App\Libraries\Elasticsearch\Search; 13use App\Libraries\Elasticsearch\SearchResponse; 14use App\Models\Forum\Post; 15use App\Models\Forum\Topic; 16use App\Models\User; 17use Illuminate\Database\Eloquent\Builder; 18 19class ForumSearch extends Search 20{ 21 public static function getHighlights(Hit $hit, string $field) 22 { 23 $highlights = $hit->highlights($field, static::HIGHLIGHT_FRAGMENT_SIZE * 2); 24 $highlightsText = implode(' ... ', $highlights); 25 26 if ($highlightsText !== '') { 27 return blade_safe($highlightsText); 28 } 29 } 30 31 public function __construct(?ForumSearchParams $params = null) 32 { 33 parent::__construct(Post::esIndexName(), $params ?? new ForumSearchParams()); 34 35 $this->source(['is_deleted','topic_id', 'post_id', 'post_time', 'poster_id', 'search_content', 'topic_title']); 36 $this->highlight( 37 (new Highlight()) 38 ->field('topic_title') 39 ->field('search_content') 40 ->fragmentSize(static::HIGHLIGHT_FRAGMENT_SIZE) 41 ->numberOfFragments(3) 42 ); 43 } 44 45 /** 46 * {@inheritdoc} 47 */ 48 public function getQuery() 49 { 50 $query = (new BoolQuery()) 51 ->filter(['terms' => ['forum_id' => $this->params->filteredForumIds()]]); 52 53 if (isset($this->params->topicId)) { 54 $query->filter(['term' => ['topic_id' => $this->params->topicId]]); 55 } 56 57 if ($this->params->queryString !== null) { 58 $query->must(QueryHelper::queryString($this->params->queryString, ['search_content', 'topic_title'])); 59 } 60 61 if (isset($this->params->username)) { 62 $user = User::lookup($this->params->username); 63 $query->filter(['term' => ['poster_id' => $user ? $user->user_id : -1]]); 64 } 65 66 $query->mustNot(['terms' => ['poster_id' => $this->params->blockedUserIds()]]); 67 68 if (!$this->params->includeDeleted) { 69 $query->mustNot(['term' => ['is_deleted' => true]]); 70 } 71 72 return $query; 73 } 74 75 public function isTopicSpecificSearch() 76 { 77 return isset($this->params->topicId); 78 } 79 80 public function data() 81 { 82 return $this->response(); 83 } 84 85 /** 86 * Returns a Builder for a Collection of all the posts that appeared in this query. 87 */ 88 public function topics(): Builder 89 { 90 return Topic::withTrashed()->whereIn('topic_id', $this->response()->ids('topic_id')); 91 } 92 93 public function response(): SearchResponse 94 { 95 return parent::response()->recordType(Topic::class)->idField('topic_id'); 96 } 97 98 /** 99 * Returns a Builder for a Collection of all the users that appeared in this query. 100 * 101 * @return Builder 102 */ 103 public function users(): Builder 104 { 105 return User::whereIn('user_id', $this->response()->ids('poster_id')); 106 } 107}