From c9a0407f47ffa63d02f187a833f7a4ac5cd855bd Mon Sep 17 00:00:00 2001 From: Daniel Klabbers Date: Thu, 14 Oct 2021 14:41:35 +0200 Subject: [PATCH] commit before i lose this beauty --- composer.json | 3 +- src/Api/Controllers/SearchController.php | 73 ++++++++++++++---------- src/Elasticsearch/TermsQuery.php | 32 +++++++++++ src/Schemas/DiscussionSchema.php | 15 +++-- 4 files changed, 84 insertions(+), 39 deletions(-) create mode 100644 src/Elasticsearch/TermsQuery.php diff --git a/composer.json b/composer.json index e3359bf..da9f1b3 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "require": { "php": ">= 8.0", "flarum/core": "^1.0.0", - "elasticsearch/elasticsearch": "7.*" + "elasticsearch/elasticsearch": "7.*", + "spatie/elasticsearch-query-builder": "^1.3.0" }, "extra": { "flarum-extension": { diff --git a/src/Api/Controllers/SearchController.php b/src/Api/Controllers/SearchController.php index 1e340e1..a165af8 100644 --- a/src/Api/Controllers/SearchController.php +++ b/src/Api/Controllers/SearchController.php @@ -2,6 +2,7 @@ namespace Blomstra\Search\Api\Controllers; +use Blomstra\Search\Elasticsearch\TermsQuery; use Blomstra\Search\Schemas\Schema; use Elasticsearch\Client; use Flarum\Api\Controller\AbstractListController; @@ -13,6 +14,10 @@ use Illuminate\Contracts\Container\Container; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Psr\Http\Message\ServerRequestInterface; +use Spatie\ElasticsearchQueryBuilder\Builder; +use Spatie\ElasticsearchQueryBuilder\Queries\BoolQuery; +use Spatie\ElasticsearchQueryBuilder\Queries\MultiMatchQuery; +use Spatie\ElasticsearchQueryBuilder\Queries\TermQuery; use Tobscure\JsonApi\Document; class SearchController extends AbstractListController @@ -30,23 +35,23 @@ class SearchController extends AbstractListController $schema = $this->getSchema($index); - $result = $client->search([ - 'index' => $index, - 'from' => $this->extractOffset($request), - 'size' => $this->extractLimit($request), - 'sort' => $this->extractSort($request), - 'body' => [ - 'query' => [ - 'multi_match' => [ - 'query' => $filters['q'], - 'fields' => array_keys($schema->fulltext(new ($schema::model()))) - ] - ] - ] - ]); - $this->serializer = $schema::serializer(); + $filterQuery = (BoolQuery::create()) + ->add( + MultiMatchQuery::create($filters['q'], array_keys($schema->fulltext(new ($schema::model())))), + 'must' + ); + + $result = (new Builder($client)) + ->index($index) + ->size($this->extractLimit($request)) + ->from($this->extractOffset($request)) + ->addQuery( + $this->addFilters($filterQuery, $actor) + ) + ->search(); + $ids = Collection::make(Arr::get($result, 'hits.hits'))->pluck('_id')->toArray(); return $schema::model()::query()->findMany($ids); @@ -69,7 +74,7 @@ class SearchController extends AbstractListController return $manager->isEnabled($extension); } - protected function getFilters(User $actor): string + protected function addFilters(BoolQuery $query, User $actor): BoolQuery { /** @var Collection $groups */ $groups = $actor->groups->pluck('id'); @@ -78,22 +83,30 @@ class SearchController extends AbstractListController if ($actor->is_email_confirmed) $groups->add(Group::MEMBER_ID); - $filters = sprintf( - '(%s)', - join(' OR ', $groups->map(function(int $id) { - return "groups = $id"; - })->toArray()) - ); + $subQuery = BoolQuery::create() + ->add(TermQuery::create('private', 'false')) + ->add(TermsQuery::create('groups', $groups->toArray())); - if ($this->extensionEnabled('fof-byobu')) { - $filters .= sprintf( - " OR (private = true AND (recipient-users = $actor->id OR %s))", - join(' OR ', $groups->map(function(int $id) { - return "recipient-groups = $id"; - })->toArray()) - ); + if ($this->extensionEnabled('fof-byobu') && $actor->exists) { + $byobuQuery = BoolQuery::create() + ->add(TermQuery::create('private', 'true'), 'should') + ->add( + BoolQuery::create() + ->add(TermsQuery::create('recipient-groups', $groups->toArray())) + ->add(TermQuery::create('recipient-users', $actor->id)), + 'should' + ); + + $subQuery = BoolQuery::create() + ->add($subQuery, 'should') + ->add($byobuQuery, 'should'); } - return $filters; + $query->add( + $subQuery, + 'filter' + ); + + return $query; } } diff --git a/src/Elasticsearch/TermsQuery.php b/src/Elasticsearch/TermsQuery.php new file mode 100644 index 0000000..a85f78c --- /dev/null +++ b/src/Elasticsearch/TermsQuery.php @@ -0,0 +1,32 @@ +field = $field; + $this->value = $value; + } + + public function toArray(): array + { + return [ + 'terms' => [ + $this->field => $this->value, + ], + ]; + } +} diff --git a/src/Schemas/DiscussionSchema.php b/src/Schemas/DiscussionSchema.php index 93eade8..0c19cd8 100644 --- a/src/Schemas/DiscussionSchema.php +++ b/src/Schemas/DiscussionSchema.php @@ -18,7 +18,11 @@ class DiscussionSchema extends Schema { $filters = []; - $permissions = null; + $permissions = collect(); + + $globalPermission = Permission::query() + ->where('permission', 'viewForum') + ->pluck('group_id'); if ($this->extensionEnabled('flarum-tags')) { /** @var \Illuminate\Database\Eloquent\Collection $tags */ @@ -44,13 +48,8 @@ class DiscussionSchema extends Schema })->flatten(); } - if (! $discussion->is_private && (! $permissions || $permissions->isEmpty())) { - $permissions = Permission::query() - ->where('permission', 'viewForum') - ->pluck('group_id'); - - } else { - $permissions = collect(); + if (! $discussion->is_private && $permissions->isEmpty()) { + $permissions = $globalPermission; } $filters['groups'] = $permissions->toArray();