|
12 | 12 | use Statamic\CP\Column; |
13 | 13 | use Statamic\Facades\Blink; |
14 | 14 | use Statamic\Facades\Scope; |
| 15 | +use Statamic\Facades\Search; |
15 | 16 | use Statamic\Fieldtypes\Relationship; |
16 | | -use Statamic\Query\Builder as BaseStatamicBuilder; |
| 17 | +use Statamic\Http\Requests\FilteredRequest; |
17 | 18 | use Statamic\Query\Scopes\Filter; |
| 19 | +use Statamic\Search\Index; |
| 20 | +use Statamic\Search\QueryBuilder as SearchQueryBuilder; |
18 | 21 | use Statamic\Search\Result; |
19 | 22 | use StatamicRadPack\Runway\Http\Resources\CP\FieldtypeModel; |
20 | 23 | use StatamicRadPack\Runway\Http\Resources\CP\FieldtypeModels; |
@@ -99,6 +102,11 @@ protected function configFieldItems(): array |
99 | 102 | 'type' => 'text', |
100 | 103 | 'width' => 50, |
101 | 104 | ], |
| 105 | + 'search_index' => [ |
| 106 | + 'display' => __('Search Index'), |
| 107 | + 'instructions' => __('An appropriate search index will be used automatically where possible, but you may define an explicit one.'), |
| 108 | + 'type' => 'text', |
| 109 | + ], |
102 | 110 | 'query_scopes' => [ |
103 | 111 | 'display' => __('Query Scopes'), |
104 | 112 | 'instructions' => __('Select which query fields should be applied when retrieving selectable models.'), |
@@ -162,44 +170,68 @@ public function process($data) |
162 | 170 |
|
163 | 171 | public function getIndexItems($request) |
164 | 172 | { |
165 | | - $resource = $this->resource(); |
166 | | - |
167 | 173 | $query = $this->getIndexQuery($request); |
168 | 174 |
|
169 | | - $searchQuery = $request->search ?? false; |
| 175 | + $this->applyOrderingToIndexQuery($query, $request); |
| 176 | + |
| 177 | + $results = ($paginate = $request->boolean('paginate', true)) ? $query->paginate() : $query->get(); |
| 178 | + |
| 179 | + $items = $results->map(fn ($item) => $item instanceof Result ? $item->getSearchable()->model() : $item); |
170 | 180 |
|
171 | | - $query = $this->applySearch($resource, $query, $searchQuery); |
| 181 | + return $paginate ? $results->setCollection($items) : $items; |
| 182 | + } |
172 | 183 |
|
173 | | - $query->when(method_exists($query, 'getQuery') && $query->getQuery()->orders, function ($query) use ($request, $resource) { |
| 184 | + private function applyOrderingToIndexQuery(Builder|SearchQueryBuilder $query, FilteredRequest $request): void |
| 185 | + { |
| 186 | + $query->when(method_exists($query, 'getQuery') && $query->getQuery()->orders, function ($query) use ($request) { |
174 | 187 | if ($orderBy = $request->input('sort')) { |
175 | 188 | // The stack selector always uses `title` as the default sort column, but |
176 | | - // the "title field" for the model might be a different column so we need to convert it. |
177 | | - $sortColumn = $orderBy === 'title' ? $resource->titleField() : $orderBy; |
| 189 | + // the "title field" for the model might be a different column, so we need to convert it. |
| 190 | + $sortColumn = $orderBy === 'title' ? $this->resource()->titleField() : $orderBy; |
178 | 191 |
|
179 | 192 | $query->reorder($sortColumn, $request->input('order')); |
180 | 193 | } |
181 | | - }, fn ($query) => $query->orderBy($resource->orderBy(), $resource->orderByDirection())); |
| 194 | + }, fn ($query) => $query->orderBy($this->resource()->orderBy(), $this->resource()->orderByDirection())); |
| 195 | + } |
182 | 196 |
|
183 | | - $results = ($paginate = $request->boolean('paginate', true)) ? $query->paginate() : $query->get(); |
| 197 | + protected function getIndexQuery(FilteredRequest $request): Builder|SearchQueryBuilder |
| 198 | + { |
| 199 | + $query = $this->resource()->newEloquentQuery(); |
184 | 200 |
|
185 | | - if ($searchQuery && $resource->hasSearchIndex()) { |
186 | | - $results->setCollection($results->getCollection()->map(fn ($item) => $item->getSearchable()->model())); |
187 | | - } |
| 201 | + $query = $this->toSearchQuery($query, $request); |
188 | 202 |
|
189 | | - $items = $results->map(fn ($item) => $item instanceof Result ? $item->getSearchable() : $item); |
| 203 | + $query->when($query instanceof Builder && $query->hasNamedScope('runwayListing'), fn ($query) => $query->runwayListing()); |
190 | 204 |
|
191 | | - return $paginate ? $results->setCollection($items) : $items; |
| 205 | + $this->applyIndexQueryScopes($query, $request->all()); |
| 206 | + |
| 207 | + return $query; |
192 | 208 | } |
193 | 209 |
|
194 | | - protected function getIndexQuery($request) |
| 210 | + private function toSearchQuery(Builder $query, FilteredRequest $request): Builder|SearchQueryBuilder |
195 | 211 | { |
196 | | - $query = $this->resource()->newEloquentQuery(); |
| 212 | + if (! $search = $request->search) { |
| 213 | + return $query; |
| 214 | + } |
197 | 215 |
|
198 | | - $query->when($query->hasNamedScope('runwayListing'), fn ($query) => $query->runwayListing()); |
| 216 | + if ($index = $this->getSearchIndex()) { |
| 217 | + return $index->search($search); |
| 218 | + } |
199 | 219 |
|
200 | | - $this->applyIndexQueryScopes($query, $request->all()); |
| 220 | + return $query->runwaySearch($search); |
| 221 | + } |
201 | 222 |
|
202 | | - return $query; |
| 223 | + private function getSearchIndex(): ?Index |
| 224 | + { |
| 225 | + $index = $this->getExplicitSearchIndex() ?? $this->resource()->searchIndex(); |
| 226 | + |
| 227 | + return $index?->ensureExists(); |
| 228 | + } |
| 229 | + |
| 230 | + private function getExplicitSearchIndex(): ?Index |
| 231 | + { |
| 232 | + return ($explicit = $this->config('search_index')) |
| 233 | + ? Search::in($explicit) |
| 234 | + : null; |
203 | 235 | } |
204 | 236 |
|
205 | 237 | public function getResourceCollection($request, $items) |
@@ -370,19 +402,6 @@ protected function statusIcons() |
370 | 402 | return $resource->hasPublishStates(); |
371 | 403 | } |
372 | 404 |
|
373 | | - private function applySearch(Resource $resource, Builder $query, string $searchQuery): Builder|BaseStatamicBuilder |
374 | | - { |
375 | | - if (! $searchQuery) { |
376 | | - return $query; |
377 | | - } |
378 | | - |
379 | | - if ($resource->hasSearchIndex() && ($index = $resource->searchIndex())) { |
380 | | - return $index->ensureExists()->search($searchQuery); |
381 | | - } |
382 | | - |
383 | | - return $query->runwaySearch($searchQuery); |
384 | | - } |
385 | | - |
386 | 405 | private function resource(): Resource |
387 | 406 | { |
388 | 407 | return Runway::findResource($this->config('resource')); |
|
0 commit comments