Skip to content

Commit

Permalink
fix: allow for additional default filters
Browse files Browse the repository at this point in the history
  • Loading branch information
imorland committed Dec 15, 2023
1 parent bc4c7d1 commit c6f167e
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 3 deletions.
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
},
"optional-dependencies": [
"fof/byobu",
"fof/follow-tags"
"fof/follow-tags",
"flarum/sticky"
]
},
"flagrow": {
Expand All @@ -70,7 +71,8 @@
"fof/byobu": "*",
"fof/follow-tags": "*",
"flarum/testing": "^1.0.0",
"flarum/phpstan": "*"
"flarum/phpstan": "*",
"flarum/sticky": "*"
},
"autoload-dev": {
"psr-4": {
Expand Down
3 changes: 3 additions & 0 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
->patch('/fof/discussion-language/{id}', 'fof.discussion-language.update', Api\Controllers\UpdateLanguageController::class)
->delete('/fof/discussion-language/{id}', 'fof.discussion-language.delete', Api\Controllers\DeleteLanguageController::class),

(new Extend\ServiceProvider())
->register(Provider\LanguageFilterProvider::class),

(new Extend\Middleware('forum'))
->add(Middleware\AddLanguageFilter::class),

Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/AddLanguageFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected function addQueryParams(ServerRequestInterface $request, array $params
return $request->withQueryParams($newParams);
}

protected function isDiscussionListPath($request)
protected function isDiscussionListPath(ServerRequestInterface $request)
{
$path = $request->getAttribute('originalUri')->getPath();

Expand Down
26 changes: 26 additions & 0 deletions src/Provider/LanguageFilterProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace FoF\DiscussionLanguage\Provider;

use Flarum\Discussion\Filter\DiscussionFilterer;
use Flarum\Foundation\AbstractServiceProvider;
use Flarum\Sticky\PinStickiedDiscussionsToTop;
use FoF\DiscussionLanguage\Sticky\PinStickiedDiscussionsToTop as CustomPinStickiedDiscussionsToTop;

class LanguageFilterProvider extends AbstractServiceProvider
{
public function register()
{
$this->container->extend('flarum.filter.filter_mutators', function ($mutators) {
if (isset($mutators[DiscussionFilterer::class]) && is_array($mutators[DiscussionFilterer::class])) {
foreach ($mutators[DiscussionFilterer::class] as $key => $mutator) {
if ($mutator === PinStickiedDiscussionsToTop::class) {
$mutators[DiscussionFilterer::class][$key] = CustomPinStickiedDiscussionsToTop::class;
}
}
}

return $mutators;
});
}
}
77 changes: 77 additions & 0 deletions src/Sticky/PinStickiedDiscussionsToTop.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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 FoF\DiscussionLanguage\Sticky;

use Flarum\Filter\FilterState;
use Flarum\Query\QueryCriteria;
use Flarum\Tags\Query\TagFilterGambit;

class PinStickiedDiscussionsToTop
{
public function __invoke(FilterState $filterState, QueryCriteria $criteria)
{
if ($criteria->sortIsDefault) {
$query = $filterState->getQuery();

// If we are viewing a specific tag, then pin all stickied
// discussions to the top no matter what.
$filters = $filterState->getActiveFilters();

if (count($filters) > 0) {
// Use array_filter to check if any of the filters is an instance of TagFilterGambit
$tagFilterGambits = array_filter($filters, function($filter) {
return $filter instanceof TagFilterGambit;
});

// Check if there is at least one TagFilterGambit instance
if (count($tagFilterGambits) > 0) {
if (!is_array($query->orders)) {
$query->orders = [];
}

array_unshift($query->orders, ['column' => 'is_sticky', 'direction' => 'desc']);
}

return;
}

// Otherwise, if we are viewing "all discussions", only pin stickied
// discussions to the top if they are unread. To do this in a
// performant way we create another query which will select all
// stickied discussions, marry them into the main query, and then
// reorder the unread ones up to the top.
$sticky = clone $query;
$sticky->where('is_sticky', true);
unset($sticky->orders);

$query->union($sticky);

$read = $query->newQuery()
->selectRaw('1')
->from('discussion_user as sticky')
->whereColumn('sticky.discussion_id', 'id')
->where('sticky.user_id', '=', $filterState->getActor()->id)
->whereColumn('sticky.last_read_post_number', '>=', 'last_post_number');

// Add the bindings manually (rather than as the second
// argument in orderByRaw) for now due to a bug in Laravel which
// would add the bindings in the wrong order.
$query->orderByRaw('is_sticky and not exists ('.$read->toSql().') and last_posted_at > ? desc')
->addBinding(array_merge($read->getBindings(), [$filterState->getActor()->marked_all_as_read_at ?: 0]), 'union');

$query->unionOrders = array_merge($query->unionOrders, $query->orders);
$query->unionLimit = $query->limit;
$query->unionOffset = $query->offset;

$query->limit = $sticky->limit = $query->offset + $query->limit;
unset($query->offset, $sticky->offset);
}
}
}

0 comments on commit c6f167e

Please sign in to comment.