From 4e5f8dce11967b25f9ee16ded9c29949f4978e7d Mon Sep 17 00:00:00 2001 From: IanM Date: Wed, 6 Nov 2024 22:59:36 +0000 Subject: [PATCH 1/3] feat: add a solution filter for the posts endpoint --- extend.php | 4 +++ src/Search/BestAnswerPostFilter.php | 40 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/Search/BestAnswerPostFilter.php diff --git a/extend.php b/extend.php index e2ff0b4..cb0e77d 100644 --- a/extend.php +++ b/extend.php @@ -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; @@ -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; diff --git a/src/Search/BestAnswerPostFilter.php b/src/Search/BestAnswerPostFilter.php new file mode 100644 index 0000000..7fe2b18 --- /dev/null +++ b/src/Search/BestAnswerPostFilter.php @@ -0,0 +1,40 @@ +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'); + } + } +} From d947be92afcefa8951fc875bf916f73d1f26cec5 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 6 Nov 2024 22:59:50 +0000 Subject: [PATCH 2/3] Apply fixes from StyleCI --- src/Search/BestAnswerPostFilter.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Search/BestAnswerPostFilter.php b/src/Search/BestAnswerPostFilter.php index 7fe2b18..e79e9c6 100644 --- a/src/Search/BestAnswerPostFilter.php +++ b/src/Search/BestAnswerPostFilter.php @@ -1,5 +1,14 @@ Date: Wed, 6 Nov 2024 23:07:35 +0000 Subject: [PATCH 3/3] constrain to within Q&A tags --- src/Search/BestAnswerPostFilter.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Search/BestAnswerPostFilter.php b/src/Search/BestAnswerPostFilter.php index e79e9c6..feccc62 100644 --- a/src/Search/BestAnswerPostFilter.php +++ b/src/Search/BestAnswerPostFilter.php @@ -13,8 +13,10 @@ 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 { @@ -45,5 +47,20 @@ protected function constrain(Builder $query, User $actor, bool $negate) $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'); } }