Skip to content

Commit

Permalink
feat: allow getting total search results and replacing filters (#3906)
Browse files Browse the repository at this point in the history
* feat: allow accessing total search results
* feat: allow replacing filters
* chore: phpstan
  • Loading branch information
SychO9 authored Oct 21, 2023
1 parent 3069498 commit 73ff024
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 6 deletions.
37 changes: 34 additions & 3 deletions framework/core/src/Extend/SearchDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Flarum\Search\SearchCriteria;
use Flarum\Search\SearchState;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\Arr;

class SearchDriver implements ExtenderInterface
{
Expand Down Expand Up @@ -64,7 +65,28 @@ public function addSearcher(string $modelClass, string $searcherClass): self
*/
public function addFilter(string $searcherClass, string $filterClass): self
{
$this->filters[$searcherClass][] = $filterClass;
$this->filters[$searcherClass][] = compact('filterClass');

return $this;
}

/**
* Replace a filter from this searcher. Filters are used to filter search queries.
*
* @param class-string<AbstractSearcher> $searcherClass : The class of the Searcher for this model
* This searcher must implement \Flarum\Search\SearcherInterface.
* Or extend \Flarum\Search\Database\AbstractSearcher if using the default driver.
* @param class-string<FilterInterface> $replaceFilterClass : The ::class attribute of the filter you are replacing.
* @param class-string<FilterInterface> $filterClass : The ::class attribute of the filter you are adding.
* This filter must implement \Flarum\Search\FilterInterface
* @return self
*/
public function replaceFilter(string $searcherClass, string $replaceFilterClass, string $filterClass): self
{
$this->filters[$searcherClass][] = [
'replace' => $replaceFilterClass,
'filterClass' => $filterClass,
];

return $this;
}
Expand Down Expand Up @@ -130,9 +152,18 @@ public function extend(Container $container, Extension $extension = null): void

$container->extend('flarum.search.filters', function (array $oldFilters) {
foreach ($this->filters as $searcherClass => $filters) {
$oldFilters[$searcherClass] = array_merge(
// Start by removing any filters that will be replaced.
$oldFilters[$searcherClass] = array_filter(
$oldFilters[$searcherClass] ?? [],
$filters
function ($filter) use ($filters) {
return ! in_array($filter, Arr::pluck($filters, 'replace'));
}
);

// Add the new filters.
$oldFilters[$searcherClass] = array_merge(
$oldFilters[$searcherClass],
Arr::pluck($filters, 'filterClass')
);
}

Expand Down
29 changes: 27 additions & 2 deletions framework/core/src/Search/Database/AbstractSearcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

namespace Flarum\Search\Database;

use Closure;
use Flarum\Search\Filter\FilterManager;
use Flarum\Search\SearchCriteria;
use Flarum\Search\SearcherInterface;
use Flarum\Search\SearchResults;
use Flarum\User\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;

abstract class AbstractSearcher implements SearcherInterface
Expand Down Expand Up @@ -53,7 +54,31 @@ public function search(SearchCriteria $criteria): SearchResults
$results->pop();
}

return new SearchResults($results, $areMoreResults);
return new SearchResults($results, $areMoreResults, $this->getTotalResults($query));
}

protected function getTotalResults(Builder $query): Closure
{
return function () use ($query) {
$query = $query->toBase();

if ($query->unions) {
$query->unions = null; // @phpstan-ignore-line
$query->unionLimit = null; // @phpstan-ignore-line
$query->unionOffset = null; // @phpstan-ignore-line
$query->unionOrders = null; // @phpstan-ignore-line
$query->setBindings([], 'union');
}

$query->offset = null; // @phpstan-ignore-line
$query->limit = null; // @phpstan-ignore-line
$query->orders = null; // @phpstan-ignore-line
$query->setBindings([], 'order');

return $query->getConnection()
->table($query, 'results')
->count();
};
}

protected function applySort(DatabaseSearchState $state, ?array $sort = null, bool $sortIsDefault = false): void
Expand Down
10 changes: 9 additions & 1 deletion framework/core/src/Search/SearchResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@

namespace Flarum\Search;

use Closure;
use Illuminate\Database\Eloquent\Collection;

class SearchResults
{
public function __construct(
protected Collection $results,
protected bool $areMoreResults
protected bool $areMoreResults,
/** @var Closure(): int */
protected Closure $totalResults
) {
}

Expand All @@ -28,4 +31,9 @@ public function areMoreResults(): bool
{
return $this->areMoreResults;
}

public function getTotalResults(): int
{
return ($this->totalResults)();
}
}
18 changes: 18 additions & 0 deletions framework/core/tests/integration/extenders/SearchDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Carbon\Carbon;
use Flarum\Discussion\Discussion;
use Flarum\Discussion\Search\DiscussionSearcher;
use Flarum\Discussion\Search\Filter\UnreadFilter;
use Flarum\Extend;
use Flarum\Search\AbstractFulltextFilter;
use Flarum\Search\Database\DatabaseSearchDriver;
Expand Down Expand Up @@ -124,6 +125,23 @@ public function custom_filter_has_effect_if_added()
$this->assertEquals('[]', json_encode($this->searchDiscussions('', 5, ['noResult' => '1'])));
}

/**
* @test
*/
public function existing_filter_can_be_replaced()
{
$this->extend(
(new Extend\SearchDriver(DatabaseSearchDriver::class))
->replaceFilter(DiscussionSearcher::class, UnreadFilter::class, NoResultFilter::class)
);

$this->prepDb();

$this->assertNotContains(UnreadFilter::class, $this->app()->getContainer()->make('flarum.search.filters')[DiscussionSearcher::class]);
$this->assertContains(NoResultFilter::class, $this->app()->getContainer()->make('flarum.search.filters')[DiscussionSearcher::class]);
$this->assertEquals('[]', json_encode($this->searchDiscussions('', 5, ['noResult' => '1'])));
}

/**
* @test
*/
Expand Down

0 comments on commit 73ff024

Please sign in to comment.