From c4daeeb1f2682528be2d2689e6bb42575ba79ac6 Mon Sep 17 00:00:00 2001 From: Alexander Skvortsov Date: Fri, 13 Nov 2020 01:47:15 -0500 Subject: [PATCH] Add abstract filterer system, have discussions and users controllers use that instead of default filterer system --- .../Controller/ListDiscussionsController.php | 27 +++--- src/Api/Controller/ListUsersController.php | 32 ++++--- src/Filter/Filterer.php | 84 +++++++++++++++++++ src/Filter/WrappedFilter.php | 16 ++++ 4 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 src/Filter/Filterer.php create mode 100644 src/Filter/WrappedFilter.php diff --git a/src/Api/Controller/ListDiscussionsController.php b/src/Api/Controller/ListDiscussionsController.php index dc825d9cd..574c32362 100644 --- a/src/Api/Controller/ListDiscussionsController.php +++ b/src/Api/Controller/ListDiscussionsController.php @@ -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'), diff --git a/src/Api/Controller/ListUsersController.php b/src/Api/Controller/ListUsersController.php index 5f44c0984..d99177194 100644 --- a/src/Api/Controller/ListUsersController.php +++ b/src/Api/Controller/ListUsersController.php @@ -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'), diff --git a/src/Filter/Filterer.php b/src/Filter/Filterer.php new file mode 100644 index 000000000..cd844fcde --- /dev/null +++ b/src/Filter/Filterer.php @@ -0,0 +1,84 @@ +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); + } +} diff --git a/src/Filter/WrappedFilter.php b/src/Filter/WrappedFilter.php new file mode 100644 index 000000000..a1f9be79e --- /dev/null +++ b/src/Filter/WrappedFilter.php @@ -0,0 +1,16 @@ +