From ff80cedd6b04d860e61b86b7f344dcec08664f6d Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 3 Aug 2024 06:18:46 +0200 Subject: [PATCH] Fix sort params --- app/JsonApi/V2/Accounts/AccountSchema.php | 17 +++++++++-------- .../V2/Accounts/Capabilities/AccountQuery.php | 11 ++++++----- app/Support/JsonApi/ExpandsQuery.php | 7 +++++-- app/Support/JsonApi/SortsCollection.php | 10 ++++++++-- app/Support/JsonApi/ValidateSortParameters.php | 3 +++ config/api.php | 11 +++++++++-- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/app/JsonApi/V2/Accounts/AccountSchema.php b/app/JsonApi/V2/Accounts/AccountSchema.php index 3a8bc3e4e4..03f50c3c73 100644 --- a/app/JsonApi/V2/Accounts/AccountSchema.php +++ b/app/JsonApi/V2/Accounts/AccountSchema.php @@ -35,13 +35,13 @@ class AccountSchema extends Schema Attribute::make('updated_at'), // basic info and meta data - Attribute::make('name'), - Attribute::make('active'), - Attribute::make('order'), - Attribute::make('iban'), + Attribute::make('name')->sortable(), + Attribute::make('active')->sortable(), + Attribute::make('order')->sortable(), + Attribute::make('iban')->sortable(), Attribute::make('type'), Attribute::make('account_role'), - Attribute::make('account_number'), + Attribute::make('account_number')->sortable(), // currency Attribute::make('currency_id'), @@ -52,17 +52,18 @@ class AccountSchema extends Schema Attribute::make('is_multi_currency'), // balance - Attribute::make('balance'), - Attribute::make('native_balance'), + Attribute::make('balance')->sortable(), + Attribute::make('native_balance')->sortable(), // liability things Attribute::make('liability_direction'), Attribute::make('interest'), Attribute::make('interest_period'), - Attribute::make('current_debt'), + Attribute::make('current_debt')->sortable(), // dynamic data Attribute::make('last_activity'), + Attribute::make('balance_difference')->sortable(), // only used for sort. // group Attribute::make('object_group_id'), diff --git a/app/JsonApi/V2/Accounts/Capabilities/AccountQuery.php b/app/JsonApi/V2/Accounts/Capabilities/AccountQuery.php index c7bdc57dbb..8c63b10003 100644 --- a/app/JsonApi/V2/Accounts/Capabilities/AccountQuery.php +++ b/app/JsonApi/V2/Accounts/Capabilities/AccountQuery.php @@ -62,6 +62,7 @@ class AccountQuery extends QueryAll implements HasPagination // collect sort options $sort = $this->queryParameters->sortFields(); + // collect pagination based on the page $pagination = $this->filtersPagination($this->queryParameters->page()); // check if we need all accounts, regardless of pagination @@ -76,14 +77,14 @@ class AccountQuery extends QueryAll implements HasPagination // add pagination to the query, limiting the results. if (!$needsAll) { + Log::debug('Need full dataset'); $query = $this->addPagination($query, $pagination); } // add sort and filter parameters to the query. - $query = $this->addSortParams($query, $sort); + $query = $this->addSortParams(Account::class, $query, $sort); $query = $this->addFilterParams(Account::class, $query, $filters); - // collect the result. $collection = $query->get(['accounts.*']); @@ -93,10 +94,10 @@ class AccountQuery extends QueryAll implements HasPagination $enrichment->setEnd($otherParams['end'] ?? null); $collection = $enrichment->enrich($collection); - // TODO add filters after the query, if there are filters that cannot be applied to the database but only - // to the enriched results. + // TODO add filters after the query, if there are filters that cannot be applied to the database + // TODO same for sort things. // sort the data after the query, and return it right away. - return $this->sortCollection($collection, $sort); + return $this->sortCollection(Account::class, $collection, $sort); } } diff --git a/app/Support/JsonApi/ExpandsQuery.php b/app/Support/JsonApi/ExpandsQuery.php index 529bd780b8..dfd3ef65a5 100644 --- a/app/Support/JsonApi/ExpandsQuery.php +++ b/app/Support/JsonApi/ExpandsQuery.php @@ -41,13 +41,16 @@ trait ExpandsQuery return $query->skip($skip)->take($pagination['size']); } - final protected function addSortParams(Builder $query, ?SortFields $sort): Builder + final protected function addSortParams(string $class, Builder $query, ?SortFields $sort): Builder { + $config = config('api.valid_query_sort')[$class] ?? []; if (null === $sort) { return $query; } foreach ($sort->all() as $sortField) { - $query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC'); + if (in_array($sortField->name(), $config, true)) { + $query->orderBy($sortField->name(), $sortField->isAscending() ? 'ASC' : 'DESC'); + } } return $query; diff --git a/app/Support/JsonApi/SortsCollection.php b/app/Support/JsonApi/SortsCollection.php index c943922d4a..3e3448c7f3 100644 --- a/app/Support/JsonApi/SortsCollection.php +++ b/app/Support/JsonApi/SortsCollection.php @@ -24,17 +24,23 @@ declare(strict_types=1); namespace FireflyIII\Support\JsonApi; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; use LaravelJsonApi\Core\Query\SortFields; trait SortsCollection { - protected function sortCollection(Collection $collection, ?SortFields $sortFields): Collection + protected function sortCollection(string $class, Collection $collection, ?SortFields $sortFields): Collection { + Log::debug(__METHOD__); + $config = config('api.valid_api_sort')[$class] ?? []; if (null === $sortFields) { return $collection; } foreach ($sortFields->all() as $sortField) { - $collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name()); + if (in_array($sortField->name(), $config, true)) { + Log::debug(sprintf('Sort collection by "%s"', $sortField->name())); + $collection = $sortField->isAscending() ? $collection->sortBy($sortField->name()) : $collection->sortByDesc($sortField->name()); + } } return $collection; diff --git a/app/Support/JsonApi/ValidateSortParameters.php b/app/Support/JsonApi/ValidateSortParameters.php index fecc424113..3f76a922d5 100644 --- a/app/Support/JsonApi/ValidateSortParameters.php +++ b/app/Support/JsonApi/ValidateSortParameters.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace FireflyIII\Support\JsonApi; +use Illuminate\Support\Facades\Log; use LaravelJsonApi\Core\Query\SortFields; trait ValidateSortParameters { public function needsFullDataset(string $class, ?SortFields $params): bool { + Log::debug(__METHOD__); if (null === $params) { return false; } @@ -37,6 +39,7 @@ trait ValidateSortParameters foreach ($params->all() as $field) { if (in_array($field->name(), $config, true)) { + Log::debug('TRUE'); return true; } } diff --git a/config/api.php b/config/api.php index 7ef00a2d63..d78a033250 100644 --- a/config/api.php +++ b/config/api.php @@ -43,14 +43,21 @@ return [ 'sorting' => [ 'allowed' => [ 'transactions' => ['description', 'amount'], - 'accounts' => ['name', 'active', 'iban', 'balance', 'last_activity', 'balance_difference', 'current_debt'], + 'accounts' => ['name', 'active', 'iban', 'order', 'account_number', 'balance', 'last_activity', 'balance_difference', 'current_debt'], ], ], + // valid query columns for sorting: + 'valid_query_sort' => [ + Account::class => ['id','name', 'active', 'iban', 'order'], + ], + 'valid_api_sort' => [ + Account::class => [], + ], 'full_data_set' => [ 'account' => ['last_activity', 'balance_difference', 'current_balance', 'current_debt'], ], 'valid_query_filters' => [ - Account::class => ['id','name', 'iban', 'active'], + Account::class => ['id', 'name', 'iban', 'active'], ], 'valid_api_filters' => [ Account::class => ['id', 'name', 'iban', 'active', 'type'],