Skip to content

Commit

Permalink
feat: add a solution filter for the posts endpoint (#109)
Browse files Browse the repository at this point in the history
* feat: add a solution filter for the posts endpoint

* Apply fixes from StyleCI

* constrain to within Q&A tags

---------

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
imorland and StyleCIBot authored Nov 6, 2024
1 parent 0284487 commit 93d1fa6
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
4 changes: 4 additions & 0 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Flarum\Discussion\Filter\DiscussionFilterer;
use Flarum\Discussion\Search\DiscussionSearcher;
use Flarum\Extend;
use Flarum\Post\Filter\PostFilterer;
use Flarum\Post\Post;
use Flarum\Settings\Event\Saving as SettingsSaving;
use Flarum\Tags\Api\Serializer\TagSerializer;
Expand Down Expand Up @@ -127,6 +128,9 @@
(new Extend\Filter(DiscussionFilterer::class))
->addFilter(Search\BestAnswerFilterGambit::class),

(new Extend\Filter(PostFilterer::class))
->addFilter(Search\BestAnswerPostFilter::class),

(new Extend\ApiSerializer(TagSerializer::class))
->attributes(function (TagSerializer $serializer, Tag $tag, array $attributes) {
$attributes['isQnA'] = (bool) $tag->is_qna;
Expand Down
66 changes: 66 additions & 0 deletions src/Search/BestAnswerPostFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/*
* This file is part of fof/best-answer.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\BestAnswer\Search;

use Flarum\Filter\FilterInterface;
use Flarum\Filter\FilterState;
use Flarum\Tags\Tag;
use Flarum\User\User;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Collection;

class BestAnswerPostFilter implements FilterInterface
{
public function getFilterKey(): string
{
return 'is:solution';
}

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

protected function constrain(Builder $query, User $actor, bool $negate)
{
// Join the `discussions` table to access `best_answer_post_id`.
$query->join('discussions', 'posts.discussion_id', '=', 'discussions.id')
->where('posts.type', 'comment');

if ($negate) {
// Exclude posts that are marked as the best answer
$query->where(function ($query) {
$query->whereNull('discussions.best_answer_post_id')
->orWhereColumn('posts.id', '!=', 'discussions.best_answer_post_id');
});
} else {
// Include only posts that are marked as the best answer
$query->whereNotNull('discussions.best_answer_post_id')
->whereColumn('posts.id', '=', 'discussions.best_answer_post_id');
}

// Constrain to discussions within the allowed Q&A tags
$query->whereIn('discussions.id', function ($subQuery) use ($actor) {
$subQuery->select('discussion_id')
->from('discussion_tag')
->whereIn('tag_id', $this->allowedQnATags($actor));
});
}

protected function allowedQnATags(User $actor): Collection
{
return Tag::query()
->whereVisibleTo($actor)
->where('is_qna', true)
->pluck('id');
}
}

0 comments on commit 93d1fa6

Please sign in to comment.