Skip to content

Commit

Permalink
Simple Flarum Search Extender and tests (#2483)
Browse files Browse the repository at this point in the history
  • Loading branch information
askvortsov1 authored and KyrneDev committed Feb 20, 2021
1 parent 58d7070 commit 34149b2
Show file tree
Hide file tree
Showing 12 changed files with 524 additions and 147 deletions.
3 changes: 3 additions & 0 deletions src/Discussion/Event/Searching.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
use Flarum\Discussion\Search\DiscussionSearch;
use Flarum\Search\SearchCriteria;

/**
* @deprecated beta 16, remove beta 17
*/
class Searching
{
/**
Expand Down
68 changes: 23 additions & 45 deletions src/Discussion/Search/DiscussionSearcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,16 @@

use Flarum\Discussion\DiscussionRepository;
use Flarum\Discussion\Event\Searching;
use Flarum\Search\ApplySearchParametersTrait;
use Flarum\Search\AbstractSearch;
use Flarum\Search\AbstractSearcher;
use Flarum\Search\GambitManager;
use Flarum\Search\SearchCriteria;
use Flarum\Search\SearchResults;
use Flarum\User\User;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;

class DiscussionSearcher
class DiscussionSearcher extends AbstractSearcher
{
use ApplySearchParametersTrait;

/**
* @var GambitManager
*/
protected $gambits;

/**
* @var DiscussionRepository
*/
Expand All @@ -37,53 +32,36 @@ class DiscussionSearcher
protected $events;

/**
* @param GambitManager $gambits
* @param DiscussionRepository $discussions
* @param Dispatcher $events
* @param GambitManager $gambits
* @param array $searchMutators
*/
public function __construct(GambitManager $gambits, DiscussionRepository $discussions, Dispatcher $events)
public function __construct(DiscussionRepository $discussions, Dispatcher $events, GambitManager $gambits, array $searchMutators)
{
$this->gambits = $gambits;
parent::__construct($gambits, $searchMutators);

$this->discussions = $discussions;
$this->events = $events;
}

/**
* @param SearchCriteria $criteria
* @param int|null $limit
* @param int $offset
*
* @return SearchResults
*/
public function search(SearchCriteria $criteria, $limit = null, $offset = 0)
protected function getQuery(User $actor): Builder
{
$actor = $criteria->actor;

$query = $this->discussions->query()->select('discussions.*')->whereVisibleTo($actor);
return $this->discussions->query()->select('discussions.*')->whereVisibleTo($actor);
}

// Construct an object which represents this search for discussions.
// Apply gambits to it, sort, and paging criteria. Also give extensions
// an opportunity to modify it.
$search = new DiscussionSearch($query->getQuery(), $actor);
protected function getSearch(Builder $query, User $actor): AbstractSearch
{
return new DiscussionSearch($query->getQuery(), $actor);
}

$this->gambits->apply($search, $criteria->query);
$this->applySort($search, $criteria->sort);
$this->applyOffset($search, $offset);
$this->applyLimit($search, $limit + 1);
/**
* @deprecated along with the Searching event, remove in Beta 17.
*/
protected function mutateSearch(AbstractSearch $search, SearchCriteria $criteria)
{
parent::mutateSearch($search, $criteria);

$this->events->dispatch(new Searching($search, $criteria));

// Execute the search 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.
$discussions = $query->get();

$areMoreResults = $limit > 0 && $discussions->count() > $limit;

if ($areMoreResults) {
$discussions->pop();
}

return new SearchResults($discussions, $areMoreResults);
}
}
3 changes: 3 additions & 0 deletions src/Event/AbstractConfigureGambits.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

use Flarum\Search\GambitManager;

/**
* @deprecated beta 16, removed in beta 17
*/
abstract class AbstractConfigureGambits
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/Event/ConfigureDiscussionGambits.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace Flarum\Event;

/**
* @deprecated beta 16, removed in beta 17
*/
class ConfigureDiscussionGambits extends AbstractConfigureGambits
{
}
3 changes: 3 additions & 0 deletions src/Event/ConfigureUserGambits.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace Flarum\Event;

/**
* @deprecated beta 16, removed in beta 17
*/
class ConfigureUserGambits extends AbstractConfigureGambits
{
}
99 changes: 99 additions & 0 deletions src/Extend/SimpleFlarumSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?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\Extend;

use Flarum\Extension\Extension;
use Illuminate\Contracts\Container\Container;

class SimpleFlarumSearch implements ExtenderInterface
{
private $fullTextGambit;
private $gambits = [];
private $searcher;
private $searchMutators = [];

/**
* @param string $searcherClass: The ::class attribute of the Searcher you are modifying.
* This searcher must extend \Flarum\Search\AbstractSearcher.
*/
public function __construct($searcherClass)
{
$this->searcher = $searcherClass;
}

/**
* Add a gambit to this searcher. Gambits are used to filter search queries.
*
* @param string $gambitClass: The ::class attribute of the gambit you are adding.
* This gambit must extend \Flarum\Search\AbstractRegexGambit
*/
public function addGambit($gambitClass)
{
$this->gambits[] = $gambitClass;

return $this;
}

/**
* Set the full text gambit for this searcher. The full text gambit actually executes the search.
*
* @param string $gambitClass: The ::class attribute of the full test gambit you are adding.
* This gambit must implement \Flarum\Search\GambitInterface
*/
public function setFullTextGambit($gambitClass)
{
$this->fullTextGambit = $gambitClass;

return $this;
}

/**
* Add a callback through which to run all search queries after gambits have been applied.
*
* @param callable|string $callback
*
* The callback can be a closure or an invokable class, and should accept:
* - Flarum\Search\AbstractSearch $search
* - Flarum\Search\SearchCriteria $criteria
*/
public function addSearchMutator($callback)
{
$this->searchMutators[] = $callback;

return $this;
}

public function extend(Container $container, Extension $extension = null)
{
if (! is_null($this->fullTextGambit)) {
$container->resolving('flarum.simple_search.fulltext_gambits', function ($oldFulltextGambits) {
$oldFulltextGambits[$this->searcher] = $this->fullTextGambit;

return $oldFulltextGambits;
});
}

$container->extend('flarum.simple_search.gambits', function ($oldGambits) {
foreach ($this->gambits as $gambit) {
$oldGambits[$this->searcher][] = $gambit;
}

return $oldGambits;
});

$container->extend('flarum.simple_search.search_mutators', function ($oldMutators) {
foreach ($this->searchMutators as $mutator) {
$oldMutators[$this->searcher][] = $mutator;
}

return $oldMutators;
});
}
}
81 changes: 81 additions & 0 deletions src/Search/AbstractSearcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?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\Search;

use Flarum\User\User;
use Illuminate\Database\Eloquent\Builder;

abstract class AbstractSearcher
{
use ApplySearchParametersTrait;

/**
* @var GambitManager
*/
protected $gambits;

/**
* @var array
*/
protected $searchMutators;

public function __construct(GambitManager $gambits, array $searchMutators)
{
$this->gambits = $gambits;
$this->searchMutators = $searchMutators;
}

abstract protected function getQuery(User $actor): Builder;

abstract protected function getSearch(Builder $query, User $actor): AbstractSearch;

protected function mutateSearch(AbstractSearch $search, SearchCriteria $criteria)
{
foreach ($this->searchMutators as $mutator) {
$mutator($search, $criteria);
}
}

/**
* @param SearchCriteria $criteria
* @param int|null $limit
* @param int $offset
*
* @return SearchResults
*/
public function search(SearchCriteria $criteria, $limit = null, $offset = 0, array $load = [])
{
$actor = $criteria->actor;

$query = $this->getQuery($actor);

$search = $this->getSearch($query, $actor);

$this->gambits->apply($search, $criteria->query);
$this->applySort($search, $criteria->sort);
$this->applyOffset($search, $offset);
$this->applyLimit($search, $limit + 1);

$this->mutateSearch($search, $criteria);

// Execute the search 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);
}
}
Loading

0 comments on commit 34149b2

Please sign in to comment.