Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/search.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

'default' => [
'driver' => 'local',
'searchables' => 'all',
'searchables' => 'content',
'fields' => ['title'],
],

Expand Down
5 changes: 5 additions & 0 deletions src/Assets/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,11 @@ public function getCpSearchResultBadge(): string
return $this->container()->title();
}

public function getCpSearchResultIcon()
{
return 'assets';
}

public function warmPresets()
{
if (! $this->isImage()) {
Expand Down
5 changes: 5 additions & 0 deletions src/Auth/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,11 @@ public function getCpSearchResultBadge(): string
return __('User');
}

public function getCpSearchResultIcon(): string
{
return 'users';
}

public function getElevatedSessionMethod(): string
{
if (! config('statamic.webauthn.allow_password_login_with_passkey', true) && $this->passkeys()->isNotEmpty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/Contracts/Search/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ public function getCpTitle(): string;
public function getCpUrl(): string;

public function getCpBadge(): string;

public function getCpIcon(): string;
}
8 changes: 8 additions & 0 deletions src/Exceptions/AllSearchablesNotSupported.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Statamic\Exceptions;

class AllSearchablesNotSupported extends \Exception
{
//
}
4 changes: 2 additions & 2 deletions src/Http/Controllers/CP/CommandPaletteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function index()

public function search(Request $request)
{
return Search::index(locale: Site::selected()->handle())
return Search::index(index: 'cp', locale: Site::selected()->handle())
->ensureExists()
->search($request->query('q'))
->get()
Expand All @@ -33,7 +33,7 @@ public function search(Request $request)
->url($result->getCpUrl())
->badge($result->getCpBadge())
->reference($result->getReference())
// ->icon() // TODO: Make dynamic for entries/terms/users?
->icon($result->getCpIcon())
->toArray();
})
->values();
Expand Down
2 changes: 1 addition & 1 deletion src/Search/Commands/Update.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private function getRequestedIndex()

// They might have entered a name as it appears in the config, but if it
// should be localized we'll get all of the localized versions.
if (collect(config('statamic.search.indexes'))->has($arg)) {
if (collect(config('statamic.search.indexes'))->put('cp', [])->has($arg)) {
return $this->indexes()->filter(fn ($index) => Str::startsWith($index->name(), $arg))->all();
}

Expand Down
19 changes: 17 additions & 2 deletions src/Search/IndexManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected function invalidImplementationMessage($name)

public function all()
{
return collect($this->app['config']['statamic.search.indexes'])->flatMap(function ($config, $name) {
return $this->indexesConfig()->flatMap(function ($config, $name) {
$sites = $config['sites'] ?? null;

if ($sites === 'all') {
Expand Down Expand Up @@ -127,11 +127,26 @@ protected function callLocalizedCustomCreator(array $config, string $name, ?stri
return $this->customCreators[$config['driver']]($this->app, $config, $name, $locale);
}

private function indexesConfig()
{
$config = collect($this->app['config']['statamic.search.indexes']);

if (! $config->has('cp')) {
$config->put('cp', [
'driver' => 'local',
'searchables' => ['content', 'users', 'addons'],
'fields' => ['title'],
]);
}

return $config;
}

protected function getConfig($name)
{
$config = $this->app['config'];

if (! $index = $config["statamic.search.indexes.$name"]) {
if (! $index = $this->indexesConfig()->get($name)) {
return null;
}

Expand Down
5 changes: 5 additions & 0 deletions src/Search/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ public function getCpBadge(): string
return $this->searchable->getCpSearchResultBadge();
}

public function getCpIcon(): string
{
return $this->searchable->getCpSearchResultIcon();
}

public function get($key, $fallback = null)
{
if ($key === 'date' && method_exists($this->searchable, 'date')) {
Expand Down
10 changes: 10 additions & 0 deletions src/Search/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ public function registerSearchableProvider($class)
app(Providers::class)->register($class);
}

public function addCpSearchable($searchable)
{
Searchables::addCpSearchable($searchable);
}

public function addContentSearchable($searchable)
{
Searchables::addContentSearchable($searchable);
}

public function __call($method, $parameters)
{
return $this->index()->$method(...$parameters);
Expand Down
5 changes: 5 additions & 0 deletions src/Search/Searchable.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public function getCpSearchResultUrl()
return $this->editUrl();
}

public function getCpSearchResultIcon()
{
return 'entry';
}

public function toSearchResult(): Result
{
return new \Statamic\Search\Result($this, Str::before($this->reference(), '::'));
Expand Down
44 changes: 43 additions & 1 deletion src/Search/Searchables.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use Statamic\Contracts\Search\Searchable;
use Statamic\Exceptions\AllSearchablesNotSupported;
use Statamic\Search\Searchables\Providers;
use Statamic\Support\Arr;
use Statamic\Support\Str;
Expand All @@ -16,24 +17,65 @@ class Searchables
protected $index;
protected $providers;
protected $manager;
protected static array $cpSearchables = [];
protected static array $contentSearchables = [];
Comment on lines +20 to +21
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if these might be better off as container bindings? 🤔


public function __construct(Index $index)
{
$this->index = $index;
$this->providers = $this->makeProviders();
}

public static function addCpSearchable($searchable)
{
if (method_exists($searchable, 'handle')) {
$searchable = $searchable::handle();
}

static::$cpSearchables[] = $searchable;
}

public static function clearCpSearchables()
{
static::$cpSearchables = [];
}

public static function addContentSearchable($searchable)
{
if (method_exists($searchable, 'handle')) {
$searchable = $searchable::handle();
}

static::$contentSearchables[] = $searchable;
}

public static function clearContentSearchables()
{
static::$contentSearchables = [];
}

private function makeProviders()
{
$manager = app(Providers::class);

$providers = collect(Arr::wrap($this->index->config()['searchables'] ?? []));

if ($providers->contains('all')) {
return $manager->providers()->map(fn ($_, $key) => $manager->make($key, $this->index, ['*']));
throw new AllSearchablesNotSupported("'searchables' => 'all' is no longer supported. Please see the upgrade guide for more information: https://statamic.dev/getting-started/upgrade-guide/5-to-6");
}

return $providers
->flatMap(function ($key) {
if ($key === 'content') {
return ['collection:*', 'taxonomy:*', 'assets:*', ...static::$contentSearchables];
}

if ($key === 'addons') {
return static::$cpSearchables;
}

return [$key];
})
->map(fn ($key) => ['provider' => Str::before($key, ':'), 'key' => Str::after($key, ':')])
->groupBy('provider')
->map(fn ($items, $provider) => $manager->make($provider, $this->index, $items->map->key->all()));
Expand Down
5 changes: 5 additions & 0 deletions src/Taxonomies/LocalizedTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,11 @@ public function getCpSearchResultBadge()
return $this->taxonomy()->title();
}

public function getCpSearchResultIcon()
{
return 'taxonomies';
}

public function getBulkAugmentationReferenceKey(): ?string
{
if ($this->augmentationReferenceKey) {
Expand Down
53 changes: 52 additions & 1 deletion tests/Search/IndexManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function it_gets_indexes()

$manager = new IndexManager($this->app);

$this->assertEquals(['foo', 'bar_en', 'bar_fr', 'baz_en', 'baz_fr', 'baz_de'], $manager->all()->map->name()->values()->all());
$this->assertEquals(['foo', 'bar_en', 'bar_fr', 'baz_en', 'baz_fr', 'baz_de', 'cp'], $manager->all()->map->name()->values()->all());

$this->assertInstanceOf(NullIndex::class, $foo = $manager->index('foo'));
$this->assertEquals('foo', $foo->name());
Expand Down Expand Up @@ -75,4 +75,55 @@ public function it_gets_indexes()
$this->assertEquals('Search index [bar] has not been configured for the [de] site.', $e->getMessage());
}
}

#[Test]
public function it_builds_the_cp_index_if_it_doesnt_exist_in_the_config()
{
config(['statamic.search.indexes' => [
'default' => [
'driver' => 'local',
'searchables' => 'content',
'fields' => ['title'],
],
]]);

$manager = new IndexManager($this->app);

$this->assertEquals(['default', 'cp'], $manager->all()->map->name()->values()->all());

$this->assertEquals([
'fields' => ['title'],
'path' => storage_path('statamic/search'),
'driver' => 'local',
'searchables' => ['content', 'users', 'addons'],
], $manager->index('cp')->config());
}

#[Test]
public function it_uses_the_cp_index_from_the_config_if_it_exists()
{
config(['statamic.search.indexes' => [
'default' => [
'driver' => 'local',
'searchables' => 'content',
'fields' => ['title'],
],
'cp' => [
'driver' => 'local',
'searchables' => ['collections:pages', 'collections:blog'],
'fields' => ['title', 'excerpt'],
],
]]);

$manager = new IndexManager($this->app);

$this->assertEquals(['default', 'cp'], $manager->all()->map->name()->values()->all());

$this->assertEquals([
'fields' => ['title', 'excerpt'],
'path' => storage_path('statamic/search'),
'driver' => 'local',
'searchables' => ['collections:pages', 'collections:blog'],
], $manager->index('cp')->config());
}
}
16 changes: 8 additions & 8 deletions tests/Search/Searchables/AssetsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public function it_gets_assets($locale, $config, $expected)
public static function assetsProvider()
{
return [
'all' => [
'content' => [
null,
['searchables' => 'all'],
['searchables' => 'content'],
['a', 'b', 'y', 'z'],
],
'all containers' => [
Expand All @@ -77,9 +77,9 @@ public static function assetsProvider()
['y', 'z'],
],

'all, english' => [
'content, english' => [
'en',
['searchables' => 'all'],
['searchables' => 'content'],
['a', 'b', 'y', 'z'],
],
'all containers, english' => [
Expand All @@ -98,9 +98,9 @@ public static function assetsProvider()
['y', 'z'],
],

'all, french' => [
'content, french' => [
'fr',
['searchables' => 'all'],
['searchables' => 'content'],
['a', 'b', 'y', 'z'],
],
'all containers, french' => [
Expand Down Expand Up @@ -138,7 +138,7 @@ public function it_can_use_a_custom_filter($filter)
$d = tap(Asset::make()->container('images')->path('d.jpg'))->save();

$provider = $this->makeProvider(null, [
'searchables' => 'all',
'searchables' => 'content',
'filter' => $filter,
]);

Expand Down Expand Up @@ -185,7 +185,7 @@ private function normalizeSearchableKeys($keys)
{
// a bit of duplicated implementation logic.
// but it makes the test look more like the real thing.
return collect($keys === 'all' ? ['*'] : $keys)
return collect($keys === 'content' ? ['*'] : $keys)
->map(fn ($key) => str_replace('assets:', '', $key))
->all();
}
Expand Down
Loading