Skip to content

Commit

Permalink
[4.x] Improve Entries fieldtype search index logic, and add option to…
Browse files Browse the repository at this point in the history
… define an explicit one. (#8885)

Co-authored-by: Jason Varga <[email protected]>
  • Loading branch information
edalzell and jasonvarga authored Oct 27, 2023
1 parent 9927909 commit 26e5277
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
1 change: 1 addition & 0 deletions resources/lang/en/fieldtypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
'entries.config.create' => 'Allow creation of new entries.',
'entries.config.collections' => 'Choose which collections the user can select from.',
'entries.config.query_scopes' => 'Choose which query scopes should be applied when retrieving selectable entries.',
'entries.config.search_index' => 'An appropriate search index will be used automatically where possible, but you may define an explicit one.',
'entries.title' => 'Entries',
'float.title' => 'Float',
'form.config.max_items' => 'Set a maximum number of selectable forms.',
Expand Down
67 changes: 51 additions & 16 deletions src/Fieldtypes/Entries.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Statamic\Facades\Entry;
use Statamic\Facades\GraphQL;
use Statamic\Facades\Scope;
use Statamic\Facades\Search;
use Statamic\Facades\Site;
use Statamic\Facades\User;
use Statamic\Http\Resources\CP\Entries\Entries as EntriesResource;
Expand All @@ -18,6 +19,7 @@
use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters;
use Statamic\Query\Scopes\Filters\Fields\Entries as EntriesFilter;
use Statamic\Query\StatusQueryBuilder;
use Statamic\Search\Index;
use Statamic\Search\Result;
use Statamic\Support\Arr;

Expand Down Expand Up @@ -91,6 +93,11 @@ protected function configFieldItems(): array
'type' => 'collections',
'mode' => 'select',
],
'search_index' => [
'display' => __('Search Index'),
'instructions' => __('statamic::fieldtypes.entries.config.search_index'),
'type' => 'text',
],
'query_scopes' => [
'display' => __('Query Scopes'),
'instructions' => __('statamic::fieldtypes.entries.config.query_scopes'),
Expand Down Expand Up @@ -182,22 +189,7 @@ protected function getIndexQuery($request)
{
$query = Entry::query();

if ($search = $request->search) {
$usingSearchIndex = false;
$collections = collect($this->getConfiguredCollections());

if ($collections->count() == 1) {
$collection = Collection::findByHandle($collections->first());
if ($collection && $collection->hasSearchIndex()) {
$query = $collection->searchIndex()->ensureExists()->search($search);
$usingSearchIndex = true;
}
}

if (! $usingSearchIndex) {
$query->where('title', 'like', '%'.$search.'%');
}
}
$query = $this->toSearchQuery($query, $request);

if ($site = $request->site) {
$query->where('site', $site);
Expand All @@ -212,6 +204,49 @@ protected function getIndexQuery($request)
return $query;
}

private function toSearchQuery($query, $request)
{
if (! $search = $request->search) {
return $query;
}

if ($index = $this->getSearchIndex($request)) {
return $index->search($search);
}

return $query->where('title', 'like', '%'.$search.'%');
}

private function getSearchIndex($request): ?Index
{
$index = $this->getExplicitSearchIndex() ?? $this->getCollectionSearchIndex($request);

return $index?->ensureExists();
}

private function getExplicitSearchIndex(): ?Index
{
return ($explicit = $this->config('search_index'))
? Search::in($explicit)
: null;
}

private function getCollectionSearchIndex($request): ?Index
{
// Use the collections being filtered, or the configured collections.
$collections = collect(
$request->input('filters.collection.collections') ?? $this->getConfiguredCollections()
);

$indexes = $collections->map(fn ($handle) => Collection::findByHandle($handle)->searchIndex());

// If all the collections use the same index, return it.
// Even if they're all null, that's fine. It'll just return null.
return $indexes->unique()->count() === 1
? $indexes->first()
: null;
}

protected function getCreatables()
{
if ($url = $this->getCreateItemUrl()) {
Expand Down

0 comments on commit 26e5277

Please sign in to comment.