Skip to content

Commit

Permalink
Search Filter Split, Use Same Controller (#2454)
Browse files Browse the repository at this point in the history
  • Loading branch information
askvortsov1 authored Feb 24, 2021
1 parent 1c578a8 commit 023871e
Show file tree
Hide file tree
Showing 42 changed files with 1,663 additions and 535 deletions.
33 changes: 24 additions & 9 deletions src/Api/Controller/ListDiscussionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

use Flarum\Api\Serializer\DiscussionSerializer;
use Flarum\Discussion\Discussion;
use Flarum\Discussion\Filter\DiscussionFilterer;
use Flarum\Discussion\Search\DiscussionSearcher;
use Flarum\Http\UrlGenerator;
use Flarum\Search\SearchCriteria;
use Illuminate\Support\Arr;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;

Expand Down Expand Up @@ -43,11 +43,21 @@ class ListDiscussionsController extends AbstractListController
'lastPost'
];

/**
* {@inheritDoc}
*/
public $sort = ['lastPostedAt' => 'desc'];

/**
* {@inheritdoc}
*/
public $sortFields = ['lastPostedAt', 'commentCount', 'createdAt'];

/**
* @var DiscussionFilterer
*/
protected $filterer;

/**
* @var DiscussionSearcher
*/
Expand All @@ -59,11 +69,13 @@ class ListDiscussionsController extends AbstractListController
protected $url;

/**
* @param DiscussionFilterer $filterer
* @param DiscussionSearcher $searcher
* @param UrlGenerator $url
*/
public function __construct(DiscussionSearcher $searcher, UrlGenerator $url)
public function __construct(DiscussionFilterer $filterer, DiscussionSearcher $searcher, UrlGenerator $url)
{
$this->filterer = $filterer;
$this->searcher = $searcher;
$this->url = $url;
}
Expand All @@ -74,16 +86,19 @@ public function __construct(DiscussionSearcher $searcher, UrlGenerator $url)
protected function data(ServerRequestInterface $request, Document $document)
{
$actor = $request->getAttribute('actor');
$query = Arr::get($this->extractFilter($request), 'q');
$filters = $this->extractFilter($request);
$sort = $this->extractSort($request);

$criteria = new SearchCriteria($actor, $query, $sort);

$limit = $this->extractLimit($request);
$offset = $this->extractOffset($request);
$load = array_merge($this->extractInclude($request), ['state']);
$include = array_merge($this->extractInclude($request), ['state']);

$results = $this->searcher->search($criteria, $limit, $offset);
$criteria = new SearchCriteria($actor, $filters, $sort);
if (array_key_exists('q', $filters)) {
$results = $this->searcher->search($criteria, $limit, $offset);
} else {
$results = $this->filterer->filter($criteria, $limit, $offset);
}

$document->addPaginationLinks(
$this->url->to('api')->route('discussions.index'),
Expand All @@ -95,9 +110,9 @@ protected function data(ServerRequestInterface $request, Document $document)

Discussion::setStateUser($actor);

$results = $results->getResults()->load($load);
$results = $results->getResults()->load($include);

if ($relations = array_intersect($load, ['firstPost', 'lastPost'])) {
if ($relations = array_intersect($include, ['firstPost', 'lastPost'])) {
foreach ($results as $discussion) {
foreach ($relations as $relation) {
if ($discussion->$relation) {
Expand Down
26 changes: 18 additions & 8 deletions src/Api/Controller/ListUsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
use Flarum\Api\Serializer\UserSerializer;
use Flarum\Http\UrlGenerator;
use Flarum\Search\SearchCriteria;
use Flarum\User\Filter\UserFilterer;
use Flarum\User\Search\UserSearcher;
use Illuminate\Support\Arr;
use Psr\Http\Message\ServerRequestInterface;
use Tobscure\JsonApi\Document;

Expand All @@ -40,6 +40,11 @@ class ListUsersController extends AbstractListController
'joinedAt'
];

/**
* @var UserFilterer
*/
protected $filterer;

/**
* @var UserSearcher
*/
Expand All @@ -51,11 +56,13 @@ class ListUsersController extends AbstractListController
protected $url;

/**
* @param UserFilterer $filterer
* @param UserSearcher $searcher
* @param UrlGenerator $url
*/
public function __construct(UserSearcher $searcher, UrlGenerator $url)
public function __construct(UserFilterer $filterer, UserSearcher $searcher, UrlGenerator $url)
{
$this->filterer = $filterer;
$this->searcher = $searcher;
$this->url = $url;
}
Expand All @@ -69,16 +76,19 @@ protected function data(ServerRequestInterface $request, Document $document)

$actor->assertCan('viewUserList');

$query = Arr::get($this->extractFilter($request), 'q');
$filters = $this->extractFilter($request);
$sort = $this->extractSort($request);

$criteria = new SearchCriteria($actor, $query, $sort);

$limit = $this->extractLimit($request);
$offset = $this->extractOffset($request);
$load = $this->extractInclude($request);
$include = $this->extractInclude($request);

$results = $this->searcher->search($criteria, $limit, $offset, $load);
$criteria = new SearchCriteria($actor, $filters, $sort);
if (array_key_exists('q', $filters)) {
$results = $this->searcher->search($criteria, $limit, $offset);
} else {
$results = $this->filterer->filter($criteria, $limit, $offset);
}

$document->addPaginationLinks(
$this->url->to('api')->route('users.index'),
Expand All @@ -88,6 +98,6 @@ protected function data(ServerRequestInterface $request, Document $document)
$results->areMoreResults() ? null : 0
);

return $results->getResults();
return $results->getResults()->load($include);
}
}
8 changes: 4 additions & 4 deletions src/Discussion/Event/Searching.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@

namespace Flarum\Discussion\Event;

use Flarum\Discussion\Search\DiscussionSearch;
use Flarum\Search\SearchCriteria;
use Flarum\Search\SearchState;

/**
* @deprecated beta 16, remove beta 17
*/
class Searching
{
/**
* @var DiscussionSearch
* @var SearchState
*/
public $search;

Expand All @@ -28,10 +28,10 @@ class Searching
public $criteria;

/**
* @param DiscussionSearch $search
* @param SearchState $search
* @param \Flarum\Search\SearchCriteria $criteria
*/
public function __construct(DiscussionSearch $search, SearchCriteria $criteria)
public function __construct(SearchState $search, SearchCriteria $criteria)
{
$this->search = $search;
$this->criteria = $criteria;
Expand Down
72 changes: 72 additions & 0 deletions src/Discussion/Filter/AuthorFilterGambit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?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\Discussion\Filter;

use Flarum\Filter\FilterInterface;
use Flarum\Filter\FilterState;
use Flarum\Search\AbstractRegexGambit;
use Flarum\Search\SearchState;
use Flarum\User\UserRepository;
use Illuminate\Database\Query\Builder;

class AuthorFilterGambit extends AbstractRegexGambit implements FilterInterface
{
/**
* @var \Flarum\User\UserRepository
*/
protected $users;

/**
* @param \Flarum\User\UserRepository $users
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}

/**
* {@inheritdoc}
*/
public function getGambitPattern()
{
return 'author:(.+)';
}

/**
* {@inheritdoc}
*/
protected function conditions(SearchState $search, array $matches, $negate)
{
$this->constrain($search->getQuery(), $matches[1], $negate);
}

public function getFilterKey(): string
{
return 'author';
}

public function filter(FilterState $filterState, string $filterValue, bool $negate)
{
$this->constrain($filterState->getQuery(), $filterValue, $negate);
}

protected function constrain(Builder $query, $rawUsernames, $negate)
{
$usernames = trim($rawUsernames, '"');
$usernames = explode(',', $usernames);

$ids = [];
foreach ($usernames as $username) {
$ids[] = $this->users->getIdForUsername($username);
}

$query->whereIn('discussions.user_id', $ids, 'and', $negate);
}
}
61 changes: 61 additions & 0 deletions src/Discussion/Filter/CreatedFilterGambit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?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\Discussion\Filter;

use Flarum\Filter\FilterInterface;
use Flarum\Filter\FilterState;
use Flarum\Search\AbstractRegexGambit;
use Flarum\Search\SearchState;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Arr;

class CreatedFilterGambit extends AbstractRegexGambit implements FilterInterface
{
/**
* {@inheritdoc}
*/
public function getGambitPattern()
{
return 'created:(\d{4}\-\d\d\-\d\d)(\.\.(\d{4}\-\d\d\-\d\d))?';
}

/**
* {@inheritdoc}
*/
protected function conditions(SearchState $search, array $matches, $negate)
{
$this->constrain($search->getQuery(), Arr::get($matches, 1), Arr::get($matches, 3), $negate);
}

public function getFilterKey(): string
{
return 'created';
}

public function filter(FilterState $filterState, string $filterValue, bool $negate)
{
preg_match('/^'.$this->getGambitPattern().'$/i', 'created:'.$filterValue, $matches);

$this->constrain($filterState->getQuery(), Arr::get($matches, 1), Arr::get($matches, 3), $negate);
}

public function constrain(Builder $query, ?string $firstDate, ?string $secondDate, $negate)
{
// If we've just been provided with a single YYYY-MM-DD date, then find
// discussions that were started on that exact date. But if we've been
// provided with a YYYY-MM-DD..YYYY-MM-DD range, then find discussions
// that were started during that period.
if (empty($secondDate)) {
$query->whereDate('created_at', $negate ? '!=' : '=', $firstDate);
} else {
$query->whereBetween('created_at', [$firstDate, $secondDate], 'and', $negate);
}
}
}
40 changes: 40 additions & 0 deletions src/Discussion/Filter/DiscussionFilterer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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\Discussion\Filter;

use Flarum\Discussion\DiscussionRepository;
use Flarum\Filter\AbstractFilterer;
use Flarum\User\User;
use Illuminate\Database\Eloquent\Builder;

class DiscussionFilterer extends AbstractFilterer
{
/**
* @var DiscussionRepository
*/
protected $discussions;

/**
* @param DiscussionRepository $discussions
* @param array $filters
* @param array $filterMutators
*/
public function __construct(DiscussionRepository $discussions, array $filters, array $filterMutators)
{
parent::__construct($filters, $filterMutators);

$this->discussions = $discussions;
}

protected function getQuery(User $actor): Builder
{
return $this->discussions->query()->select('discussions.*')->whereVisibleTo($actor);
}
}
Loading

0 comments on commit 023871e

Please sign in to comment.