mirror of
https://github.com/filamentphp/filament.git
synced 2026-08-30 17:07:25 +08:00
feature: Global search resource opt-in (#19513)
This commit is contained in:
@@ -172,6 +172,29 @@ public function panel(Panel $panel): Panel
|
||||
}
|
||||
```
|
||||
|
||||
## Requiring resources to opt in to global search
|
||||
|
||||
By default, all resources with a [title attribute](#setting-global-search-result-titles) are included in global search results. If you'd prefer resources to explicitly opt in, you can use the `globalSearchResourceOptIn()` method in the [configuration](../panel-configuration):
|
||||
|
||||
```php
|
||||
use Filament\Panel;
|
||||
|
||||
public function panel(Panel $panel): Panel
|
||||
{
|
||||
return $panel
|
||||
// ...
|
||||
->globalSearchResourceOptIn();
|
||||
}
|
||||
```
|
||||
|
||||
Now, only resources that explicitly set `$isGloballySearchable` to `true` will be included in global search results:
|
||||
|
||||
```php
|
||||
protected static bool $isGloballySearchable = true;
|
||||
```
|
||||
|
||||
Resources that do not declare this property will be excluded from global search, even if they have a title attribute set.
|
||||
|
||||
## Registering global search key bindings
|
||||
|
||||
The global search field can be opened using keyboard shortcuts. To configure these, pass the `globalSearchKeyBindings()` method to the [configuration](../panel-configuration):
|
||||
|
||||
@@ -26,6 +26,8 @@ trait HasGlobalSearch
|
||||
|
||||
protected string | Closure | null $globalSearchFieldSuffix = null;
|
||||
|
||||
protected bool $isGlobalSearchResourceOptIn = false;
|
||||
|
||||
public function globalSearch(string | bool $provider = true, GlobalSearchPosition | Closure | null $position = null): static
|
||||
{
|
||||
if (is_string($provider) && (! in_array(GlobalSearchProvider::class, class_implements($provider)))) {
|
||||
@@ -121,6 +123,18 @@ trait HasGlobalSearch
|
||||
return $this->evaluate($this->globalSearchFieldSuffix);
|
||||
}
|
||||
|
||||
public function globalSearchResourceOptIn(bool $condition = true): static
|
||||
{
|
||||
$this->isGlobalSearchResourceOptIn = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isGlobalSearchResourceOptIn(): bool
|
||||
{
|
||||
return $this->isGlobalSearchResourceOptIn;
|
||||
}
|
||||
|
||||
public function getGlobalSearchProvider(): ?GlobalSearchProvider
|
||||
{
|
||||
$provider = $this->globalSearchProvider;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Filament\Resources\Resource\Concerns;
|
||||
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\GlobalSearch\GlobalSearchResult;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Database\Connection;
|
||||
@@ -10,6 +11,7 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function Filament\Support\generate_search_column_expression;
|
||||
use function Filament\Support\generate_search_term_expression;
|
||||
@@ -31,7 +33,18 @@ trait HasGlobalSearch
|
||||
|
||||
public static function canGloballySearch(): bool
|
||||
{
|
||||
return static::$isGloballySearchable && count(static::getGloballySearchableAttributes()) && static::canAccess();
|
||||
$isGloballySearchable = static::$isGloballySearchable;
|
||||
|
||||
if (
|
||||
$isGloballySearchable &&
|
||||
Filament::getCurrentOrDefaultPanel()?->isGlobalSearchResourceOptIn()
|
||||
) {
|
||||
$isGloballySearchable = (new ReflectionProperty(static::class, 'isGloballySearchable'))
|
||||
->getDeclaringClass()
|
||||
->getName() === static::class;
|
||||
}
|
||||
|
||||
return $isGloballySearchable && count(static::getGloballySearchableAttributes()) && static::canAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,11 @@ use Filament\GlobalSearch\GlobalSearchResult;
|
||||
use Filament\GlobalSearch\GlobalSearchResults;
|
||||
use Filament\GlobalSearch\Providers\Contracts\GlobalSearchProvider;
|
||||
use Filament\Livewire\GlobalSearch;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tests\Fixtures\Models\Post;
|
||||
use Filament\Tests\Fixtures\Models\User;
|
||||
use Filament\Tests\Fixtures\Resources\Posts\PostResource;
|
||||
use Filament\Tests\Fixtures\Resources\Users\UserResource;
|
||||
use Filament\Tests\Panels\GlobalSearch\TestCase;
|
||||
use Illuminate\Database\Eloquent\Factories\Sequence;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -78,6 +81,54 @@ it('orders resource global search results by `$globalSearchSort`', function ():
|
||||
expect($categories[1])->toBe('posts');
|
||||
});
|
||||
|
||||
it('excludes resources without explicit `$isGloballySearchable` when `globalSearchResourceOptIn()` is enabled', function (): void {
|
||||
Filament::getCurrentOrDefaultPanel()->globalSearchResourceOptIn();
|
||||
|
||||
expect(PostResource::canGloballySearch())->toBeFalse();
|
||||
expect(UserResource::canGloballySearch())->toBeFalse();
|
||||
});
|
||||
|
||||
it('includes resources with explicit `$isGloballySearchable` when `globalSearchResourceOptIn()` is enabled', function (): void {
|
||||
Filament::getCurrentOrDefaultPanel()->globalSearchResourceOptIn();
|
||||
|
||||
expect(OptedInGlobalSearchResource::canGloballySearch())->toBeTrue();
|
||||
});
|
||||
|
||||
it('includes all resources by default without `globalSearchResourceOptIn()`', function (): void {
|
||||
expect(PostResource::canGloballySearch())->toBeTrue();
|
||||
expect(UserResource::canGloballySearch())->toBeTrue();
|
||||
expect(OptedInGlobalSearchResource::canGloballySearch())->toBeTrue();
|
||||
});
|
||||
|
||||
it('does not return search results for resources without explicit `$isGloballySearchable` when `globalSearchResourceOptIn()` is enabled', function (): void {
|
||||
Filament::getCurrentOrDefaultPanel()->globalSearchResourceOptIn();
|
||||
|
||||
$post = Post::factory()->create();
|
||||
|
||||
livewire(GlobalSearch::class)
|
||||
->set('search', $post->title)
|
||||
->assertDontSee($post->title);
|
||||
});
|
||||
|
||||
class OptedInGlobalSearchResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Post::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'title';
|
||||
|
||||
protected static bool $isGloballySearchable = true;
|
||||
|
||||
protected static ?string $slug = 'opted-in-global-search-posts';
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public static function getGloballySearchableAttributes(): array
|
||||
{
|
||||
return ['title'];
|
||||
}
|
||||
}
|
||||
|
||||
class CustomSearchProvider implements GlobalSearchProvider
|
||||
{
|
||||
public function getResults(string $query): ?GlobalSearchResults
|
||||
|
||||
Reference in New Issue
Block a user