diff --git a/extend.php b/extend.php index f8c5de7..a154932 100644 --- a/extend.php +++ b/extend.php @@ -18,7 +18,20 @@ use Flarum\Api\Serializer\UserSerializer; use Flarum\Extend; use Flarum\User\Event\Saving; use Flarum\Api\Event\Serializing; - +use Flarum\User\Filter\UserFilterer; +use Flarum\Filter\FilterState; +use Flarum\Query\QueryCriteria; + +class UserLocationFilterMutator +{ + public function __invoke(FilterState $filterState, QueryCriteria $queryCriteria) + { + if($queryCriteria->mustHaveLocation) + { + $filterState->getQuery()->where('location_latitude', '!=', 'null'); + } + } +} return [ (new Extend\Frontend('forum')) @@ -37,5 +50,11 @@ return [ (new Extend\Settings)->serializeToForum('justoverclock-users-map-location.mapBox-api-key', 'justoverclock-users-map-location.mapBox-api-key'), (new Extend\Frontend('forum')) - ->route('/global-map', 'justoverclock.global-map') + ->route('/global-map', 'justoverclock.global-map'), + + (new Extend\Filter(UserFilterer::class)) + ->addFilterMutator(UserLocationFilterMutator::class), + + (new Extend\Routes('api')) + ->get('/user-locations', 'user-locations.index', Api\Controller\ListUserLocationsController::class) ]; diff --git a/src/Api/Controller/ListUserLocationsController.php b/src/Api/Controller/ListUserLocationsController.php new file mode 100644 index 0000000..59e6619 --- /dev/null +++ b/src/Api/Controller/ListUserLocationsController.php @@ -0,0 +1,100 @@ +filterer = $filterer; + $this->searcher = $searcher; + $this->url = $url; + } + + /** + * {@inheritdoc} + */ + protected function data(ServerRequestInterface $request, Document $document) + { + // See https://docs.flarum.org/extend/api.html#api-endpoints for more information. + + $actor = RequestUtil::getActor($request); + + $actor->assertCan('searchUsers'); + + if (! $actor->hasPermission('user.viewLastSeenAt')) { + // If a user cannot see everyone's last online date, we prevent them from sorting by it + // Otherwise this sort field would defeat the privacy setting discloseOnline + // We use remove instead of add so that extensions can still completely disable the sort using the extender + $this->removeSortField('lastSeenAt'); + } + + $filters = $this->extractFilter($request); + $sort = $this->extractSort($request); + $sortIsDefault = $this->sortIsDefault($request); + + $limit = $this->extractLimit($request); + $offset = $this->extractOffset($request); + $include = $this->extractInclude($request); + + $criteria = new QueryCriteria($actor, $filters, $sort, $sortIsDefault); + $criteria->mustHaveLocation = true; + if (array_key_exists('q', $filters)) { + $results = $this->searcher->search($criteria, $limit, $offset); + } else { + $results = $this->filterer->filter($criteria, $limit, $offset); + } + + $document->addPaginationLinks( + $this->url->to('api')->route('user-locations.index'), + $request->getQueryParams(), + $offset, + $limit, + $results->areMoreResults() ? null : 0 + ); + + $results = $results->getResults(); + + $this->loadRelations($results, $include, $request); + + return $results; + } +} diff --git a/src/Api/Serializer/UserLocationSerializer.php b/src/Api/Serializer/UserLocationSerializer.php new file mode 100644 index 0000000..1efae77 --- /dev/null +++ b/src/Api/Serializer/UserLocationSerializer.php @@ -0,0 +1,39 @@ + $model->username, + 'displayName' => $model->display_name, + 'location_longitude' => $model->location_longitude, + 'location_latitude' => $model->location_latitude, + ]; + } +}