1
0
mirror of https://github.com/flarum/core.git synced 2025-08-07 17:07:19 +02:00

Add abstract filterer system, have discussions and users controllers use that instead of default filterer system

This commit is contained in:
Alexander Skvortsov
2020-11-13 01:47:15 -05:00
parent 87d2f3d246
commit c4daeeb1f2
4 changed files with 136 additions and 23 deletions

View File

@@ -11,10 +11,10 @@ namespace Flarum\Api\Controller;
use Flarum\Api\Serializer\DiscussionSerializer;
use Flarum\Discussion\Discussion;
use Flarum\Discussion\DiscussionRepository;
use Flarum\Discussion\Search\DiscussionSearcher;
use Flarum\Filter\Filterer;
use Flarum\Http\UrlGenerator;
use Flarum\Search\SearchCriteria;
use Illuminate\Support\Arr;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;
@@ -49,9 +49,14 @@ class ListDiscussionsController extends AbstractListController
public $sortFields = ['lastPostedAt', 'commentCount', 'createdAt'];
/**
* @var DiscussionSearcher
* @var DiscussionRepository
*/
protected $searcher;
protected $discussions;
/**
* @var Filterer
*/
protected $filterer;
/**
* @var UrlGenerator
@@ -62,9 +67,10 @@ class ListDiscussionsController extends AbstractListController
* @param DiscussionSearcher $searcher
* @param UrlGenerator $url
*/
public function __construct(DiscussionSearcher $searcher, UrlGenerator $url)
public function __construct(DiscussionRepository $discussions, Filterer $filterer, UrlGenerator $url)
{
$this->searcher = $searcher;
$this->discussions = $discussions;
$this->filterer = $filterer;
$this->url = $url;
}
@@ -74,16 +80,17 @@ class ListDiscussionsController extends AbstractListController
protected function data(ServerRequestInterface $request, Document $document)
{
$actor = $request->getAttribute('actor');
$query = Arr::get($this->extractFilter($request), 'q');
$sort = $this->extractSort($request);
$criteria = new SearchCriteria($actor, $query, $sort);
$filters = $this->extractFilter($request);
$sort = $this->extractSort($request);
$query = $this->discussions->query();
$limit = $this->extractLimit($request);
$offset = $this->extractOffset($request);
$load = array_merge($this->extractInclude($request), ['state']);
$results = $this->searcher->search($criteria, $limit, $offset);
$results = $this->filterer->filter($actor, $query, $filters, $sort, $limit, $offset, $load);
$document->addPaginationLinks(
$this->url->to('api')->route('discussions.index'),

View File

@@ -10,10 +10,9 @@
namespace Flarum\Api\Controller;
use Flarum\Api\Serializer\UserSerializer;
use Flarum\Filter\Filterer;
use Flarum\Http\UrlGenerator;
use Flarum\Search\SearchCriteria;
use Flarum\User\Search\UserSearcher;
use Illuminate\Support\Arr;
use Flarum\User\UserRepository;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;
@@ -41,9 +40,9 @@ class ListUsersController extends AbstractListController
];
/**
* @var UserSearcher
* @var Filterer
*/
protected $searcher;
protected $filterer;
/**
* @var UrlGenerator
@@ -51,13 +50,20 @@ class ListUsersController extends AbstractListController
protected $url;
/**
* @param UserSearcher $searcher
* @param UrlGenerator $url
* @var UserRepository
*/
public function __construct(UserSearcher $searcher, UrlGenerator $url)
protected $users;
/**
* @param Filterer $filterer
* @param UrlGenerator $url
* @param UserRepository $users
*/
public function __construct(Filterer $filterer, UrlGenerator $url, UserRepository $users)
{
$this->searcher = $searcher;
$this->filterer = $filterer;
$this->url = $url;
$this->users = $users;
}
/**
@@ -69,16 +75,16 @@ class ListUsersController extends AbstractListController
$actor->assertCan('viewUserList');
$query = Arr::get($this->extractFilter($request), 'q');
$sort = $this->extractSort($request);
$query = $this->users->query();
$criteria = new SearchCriteria($actor, $query, $sort);
$filters = $this->extractFilter($request);
$sort = $this->extractSort($request);
$limit = $this->extractLimit($request);
$offset = $this->extractOffset($request);
$load = $this->extractInclude($request);
$results = $this->searcher->search($criteria, $limit, $offset, $load);
$results = $this->filterer->filter($actor, $query, $filters, $sort, $limit, $offset, $load);
$document->addPaginationLinks(
$this->url->to('api')->route('users.index'),

84
src/Filter/Filterer.php Normal file
View File

@@ -0,0 +1,84 @@
<?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\SearchResults;
use Illuminate\Support\Arr;
class Filterer
{
use ApplySearchParametersTrait;
protected static $filters = [];
protected static $filterMutators = [];
public static function addFilter($resource, $filterKey, $filter)
{
if (!array_key_exists($resource, static::$filters)) {
static::$filters[$resource] = [];
}
static::$filters[$resource][$filterKey] = $filter;
}
public static function addFilterMutator($resource, $mutator)
{
if (!array_key_exists($resource, static::$filterMutators)) {
static::$filterMutators[$resource] = [];
}
static::$filterMutators[$resource][] = $mutator;
}
/**
* @param FilterCriteria $criteria
* @param int|null $limit
* @param int $offset
*
* @return FilterResults
*/
public function filter($actor, $query, $filters, $sort = null, $limit = null, $offset = 0, array $load = [])
{
$resource = get_class($query->getModel());
$query->whereVisibleTo($actor);
foreach (Arr::get(static::$filters, $resource, []) as $filterKey => $filterCallback) {
if (array_key_exists($filterKey, $filters)) {
$filterCallback($query, $filters[$filterKey]);
}
}
$wrappedFilter = new WrappedFilter($query->getQuery(), $actor);
$this->applySort($wrappedFilter, $sort);
$this->applyOffset($wrappedFilter, $offset);
$this->applyLimit($wrappedFilter, $limit + 1);
foreach (Arr::get(static::$filterMutators, $resource, []) as $mutator) {
$mutator($wrappedFilter, $filters, $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();
}
$results->load($load);
return new SearchResults($results, $areMoreResults);
}
}

View File

@@ -0,0 +1,16 @@
<?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\AbstractSearch;
class WrappedFilter extends AbstractSearch
{
}