mirror of
https://github.com/flarum/core.git
synced 2025-10-14 00:15:51 +02:00
Search Filter Split, Use Same Controller (#2454)
This commit is contained in:
committed by
GitHub
parent
1c578a83e4
commit
023871ef86
86
src/Filter/AbstractFilterer.php
Normal file
86
src/Filter/AbstractFilterer.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Filter;
|
||||
|
||||
use Flarum\Search\ApplySearchParametersTrait;
|
||||
use Flarum\Search\SearchCriteria;
|
||||
use Flarum\Search\SearchResults;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class AbstractFilterer
|
||||
{
|
||||
use ApplySearchParametersTrait;
|
||||
|
||||
protected $filters;
|
||||
|
||||
protected $filterMutators;
|
||||
|
||||
/**
|
||||
* @param array $filters
|
||||
* @param array $filterMutators
|
||||
*/
|
||||
public function __construct(array $filters, array $filterMutators)
|
||||
{
|
||||
$this->filters = $filters;
|
||||
$this->filterMutators = $filterMutators;
|
||||
}
|
||||
|
||||
abstract protected function getQuery(User $actor): Builder;
|
||||
|
||||
/**
|
||||
* @param SearchCriteria $criteria
|
||||
* @param mixed|null $limit
|
||||
* @param int $offset
|
||||
*
|
||||
* @return SearchResults
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function filter(SearchCriteria $criteria, int $limit = null, int $offset = 0): SearchResults
|
||||
{
|
||||
$actor = $criteria->actor;
|
||||
|
||||
$query = $this->getQuery($actor);
|
||||
|
||||
$filterState = new FilterState($query->getQuery(), $actor);
|
||||
|
||||
foreach ($criteria->query as $filterKey => $filterValue) {
|
||||
$negate = false;
|
||||
if (substr($filterKey, 0, 1) == '-') {
|
||||
$negate = true;
|
||||
$filterKey = substr($filterKey, 1);
|
||||
}
|
||||
foreach (Arr::get($this->filters, $filterKey, []) as $filter) {
|
||||
$filter->filter($filterState, $filterValue, $negate);
|
||||
}
|
||||
}
|
||||
|
||||
$this->applySort($filterState, $criteria->sort);
|
||||
$this->applyOffset($filterState, $offset);
|
||||
$this->applyLimit($filterState, $limit + 1);
|
||||
|
||||
foreach ($this->filterMutators as $mutator) {
|
||||
$mutator($query, $actor, $criteria->query, $criteria->sort);
|
||||
}
|
||||
|
||||
// Execute the filter query and retrieve the results. We get one more
|
||||
// results than the user asked for, so that we can say if there are more
|
||||
// results. If there are, we will get rid of that extra result.
|
||||
$results = $query->get();
|
||||
|
||||
if ($areMoreResults = $limit > 0 && $results->count() > $limit) {
|
||||
$results->pop();
|
||||
}
|
||||
|
||||
return new SearchResults($results, $areMoreResults);
|
||||
}
|
||||
}
|
26
src/Filter/FilterInterface.php
Normal file
26
src/Filter/FilterInterface.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Filter;
|
||||
|
||||
interface FilterInterface
|
||||
{
|
||||
/**
|
||||
* This filter will only be run when a query contains a filter param with this key.
|
||||
*/
|
||||
public function getFilterKey(): string;
|
||||
|
||||
/**
|
||||
* Filters a query.
|
||||
*
|
||||
* @param FilterState $filter
|
||||
* @param string $value The value of the requested filter
|
||||
*/
|
||||
public function filter(FilterState $filterState, string $filterValue, bool $negate);
|
||||
}
|
85
src/Filter/FilterServiceProvider.php
Normal file
85
src/Filter/FilterServiceProvider.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Filter;
|
||||
|
||||
use Flarum\Discussion\Filter\AuthorFilterGambit;
|
||||
use Flarum\Discussion\Filter\CreatedFilterGambit;
|
||||
use Flarum\Discussion\Filter\DiscussionFilterer;
|
||||
use Flarum\Discussion\Filter\HiddenFilterGambit;
|
||||
use Flarum\Discussion\Filter\UnreadFilterGambit;
|
||||
use Flarum\Foundation\AbstractServiceProvider;
|
||||
use Flarum\Foundation\ContainerUtil;
|
||||
use Flarum\User\Filter\EmailFilterGambit;
|
||||
use Flarum\User\Filter\GroupFilterGambit;
|
||||
use Flarum\User\Filter\UserFilterer;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class FilterServiceProvider extends AbstractServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('flarum.filter.filters', function () {
|
||||
return [
|
||||
DiscussionFilterer::class => [
|
||||
AuthorFilterGambit::class,
|
||||
CreatedFilterGambit::class,
|
||||
HiddenFilterGambit::class,
|
||||
UnreadFilterGambit::class,
|
||||
],
|
||||
UserFilterer::class => [
|
||||
EmailFilterGambit::class,
|
||||
GroupFilterGambit::class,
|
||||
]
|
||||
];
|
||||
});
|
||||
|
||||
$this->app->singleton('flarum.filter.filter_mutators', function () {
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
// We can resolve the filter mutators in the when->needs->give callback,
|
||||
// but we need to resolve at least one regardless so we know which
|
||||
// filterers we need to register filters for.
|
||||
$filters = $this->app->make('flarum.filter.filters');
|
||||
|
||||
foreach ($filters as $filterer => $filterClasses) {
|
||||
$this->app
|
||||
->when($filterer)
|
||||
->needs('$filters')
|
||||
->give(function () use ($filterClasses) {
|
||||
$compiled = [];
|
||||
|
||||
foreach ($filterClasses as $filterClass) {
|
||||
$filter = $this->app->make($filterClass);
|
||||
$compiled[$filter->getFilterKey()][] = $filter;
|
||||
}
|
||||
|
||||
return $compiled;
|
||||
});
|
||||
|
||||
$this->app
|
||||
->when($filterer)
|
||||
->needs('$filterMutators')
|
||||
->give(function () use ($filterer) {
|
||||
return array_map(function ($filterMutatorClass) {
|
||||
return ContainerUtil::wrapCallback($filterMutatorClass, $this->app);
|
||||
}, Arr::get($this->app->make('flarum.filter.filter_mutators'), $filterer, []));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
87
src/Filter/FilterState.php
Normal file
87
src/Filter/FilterState.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Filter;
|
||||
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class FilterState
|
||||
{
|
||||
/**
|
||||
* @var Builder
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $actor;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
protected $defaultSort = [];
|
||||
|
||||
/**
|
||||
* @param Builder $query
|
||||
* @param User $actor
|
||||
*/
|
||||
public function __construct(Builder $query, User $actor, $defaultSort = [])
|
||||
{
|
||||
$this->query = $query;
|
||||
$this->actor = $actor;
|
||||
$this->defaultSort = $defaultSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query builder for the search results query.
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user who is performing the search.
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function getActor()
|
||||
{
|
||||
return $this->actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default sort order for the search.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultSort()
|
||||
{
|
||||
return $this->defaultSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default sort order for the search. This will only be applied if
|
||||
* a sort order has not been specified in the search criteria.
|
||||
*
|
||||
* @param mixed $defaultSort An array of sort-order pairs, where the column
|
||||
* is the key, and the order is the value. The order may be 'asc',
|
||||
* 'desc', or an array of IDs to order by.
|
||||
* Alternatively, a callable may be used.
|
||||
* @return mixed
|
||||
*/
|
||||
public function setDefaultSort($defaultSort)
|
||||
{
|
||||
$this->defaultSort = $defaultSort;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user