From 4e8a258b011aad190597d7953b7122fc43f4658f Mon Sep 17 00:00:00 2001 From: "i @man" <11624213+iatman@users.noreply.github.com> Date: Tue, 3 Nov 2026 04:43:05 +0800 Subject: [PATCH] Support choosing the sort type when creating or editing a user query (#8954) * Support choosing the sort type when creating or editing a user query Changes - User queries can now store a sort field (sort type), not only the sort direction. The create and edit forms expose a single combined dropdown (field + direction) that reuses the existing `index.menu.sort.*` options, matching the global reading-settings sort UI. - The "Bookmark current query" action now also remembers the current sort field, where it previously kept only the order direction. - Relabel the query sort control from "Sort by date" to "Sort by"; other languages are marked for re-translation (// TODO). - Add a CHANGELOG entry and credit the contributor in CREDITS. Implementation - `FreshRSS_UserQuery`: add an optional `sort` property mirroring `order` (constructor parsing, `toArray()`, `getSort()` falling back to the user default sort, and a `hasParameters()` check). - `configureController`: split the combined dropdown value into `sort` and `order`, validating the field against the implemented sort types (`id`, `c.name`, `date`, `f.name`, `length`, `link`, `title`, `rand`); separate `sort`/`order` request parameters are still accepted so the "bookmark current query" flow keeps working. - Views render the combined dropdown and persist `sort` as a hidden field. - `p/api/query.php`: back-fill `sort` from the saved query when the request does not provide one, mirroring the existing `order` handling. - Add unit tests covering the sort round-trip and `toArray()` inclusion. Compatibility - No database or schema change: user queries are stored in the per-user PHP config array, which keeps arbitrary keys verbatim, so no migration is required. - Upgrade: existing queries without `sort` fall back to the user default sort; behaviour is unchanged until a sort is explicitly chosen. - Downgrade: older versions ignore the extra `sort` key and keep working; re-saving under an old version simply drops the key with no data loss. - Shared query URLs without a `sort` parameter remain valid. * Refresh README translation statistics * i18n: fr --------- Co-authored-by: Alexandre Alapetite --- CHANGELOG.md | 2 ++ README.fr.md | 6 ++-- README.md | 6 ++-- app/Controllers/configureController.php | 48 ++++++++++++++++++++++--- app/Models/UserQuery.php | 20 ++++++++--- app/i18n/ar/conf.php | 2 +- app/i18n/az/conf.php | 2 +- app/i18n/cs/conf.php | 2 +- app/i18n/de/conf.php | 2 +- app/i18n/el/conf.php | 2 +- app/i18n/en-US/conf.php | 2 +- app/i18n/en/conf.php | 2 +- app/i18n/es/conf.php | 2 +- app/i18n/fa/conf.php | 2 +- app/i18n/fi/conf.php | 2 +- app/i18n/fr/conf.php | 2 +- app/i18n/fr/gen.php | 2 +- app/i18n/he/conf.php | 2 +- app/i18n/hu/conf.php | 2 +- app/i18n/id/conf.php | 2 +- app/i18n/it/conf.php | 2 +- app/i18n/ja/conf.php | 2 +- app/i18n/ko/conf.php | 2 +- app/i18n/lt/conf.php | 2 +- app/i18n/lv/conf.php | 2 +- app/i18n/nl/conf.php | 2 +- app/i18n/oc/conf.php | 2 +- app/i18n/pl/conf.php | 2 +- app/i18n/pt-BR/conf.php | 2 +- app/i18n/pt-PT/conf.php | 2 +- app/i18n/ru/conf.php | 2 +- app/i18n/sk/conf.php | 2 +- app/i18n/tr/conf.php | 2 +- app/i18n/uk/conf.php | 2 +- app/i18n/zh-CN/conf.php | 2 +- app/i18n/zh-TW/conf.php | 2 +- app/views/configure/queries.phtml | 33 +++++++++++------ app/views/helpers/configure/query.phtml | 27 +++++++++++--- p/api/query.php | 3 ++ tests/app/Models/UserQueryTest.php | 13 +++++++ 40 files changed, 160 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d8e533b..f8dcbac12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ See also [the FreshRSS releases](https://github.com/FreshRSS/FreshRSS/releases). * Compatibility * 💥 Require PHP 8.2+ (drop PHP 8.1) [#9470](https://github.com/FreshRSS/FreshRSS/pull/9470) +* Features + * User queries can define their own sort criterion (field and direction) [#8954](https://github.com/FreshRSS/FreshRSS/pull/8954) * Bug fixes * Fix HTTP Retry-After cache when proxy is used [#9508](https://github.com/FreshRSS/FreshRSS/pull/9508) * Fix 32-bit systems provide a string for SQL BIGINT [#9486](https://github.com/FreshRSS/FreshRSS/pull/9486) diff --git a/README.fr.md b/README.fr.md index 616b2d893..b6ec13dd8 100644 --- a/README.fr.md +++ b/README.fr.md @@ -239,7 +239,7 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio | العربية (ar) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Far+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Azərbaycanca (az) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Faz+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Беларуская (be) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fbe+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Čeština (cs) | ■■■■■■■■・・ 81% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Čeština (cs) | ■■■■■■■■・・ 80% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Deutsch (de) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Ελληνικά (el) | ■■■■■■■・・・ 75% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fel+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | English (en) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | @@ -247,7 +247,7 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio | Español (es) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fes+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | فارسی (fa) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffa+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Suomi (fi) | ■■■■■■■■■・ 91% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Français (fr) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Français (fr) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | עברית (he) | ■■■■・・・・・・ 41% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhe+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Magyar (hu) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Bahasa Indonesia (id) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | @@ -258,7 +258,7 @@ Voir le [dépôt dédié à ces extensions](https://github.com/FreshRSS/Extensio | Latviešu (lv) | ■■■■■■■■・・ 81% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Nederlands (nl) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Occitan (oc) | ■■■■■■■・・・ 73% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Polski (pl) | ■■■■■■■■■■ 100% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Polski (pl) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Português (Brasil) (pt-BR) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Português (Portugal) (pt-PT) | ■■■■■■■■■・ 99% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-PT+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Русский (ru) | ■■■■■■■■■・ 98% | [contribuer](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fru+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | diff --git a/README.md b/README.md index f29b765f7..9ba32e2da 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E | العربية (ar) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Far+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Azərbaycanca (az) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Faz+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Беларуская (be) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fbe+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Čeština (cs) | ■■■■■■■■・・ 81% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Čeština (cs) | ■■■■■■■■・・ 80% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fcs+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Deutsch (de) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fde+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Ελληνικά (el) | ■■■■■■■・・・ 75% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fel+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | English (en) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fen+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | @@ -143,7 +143,7 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E | Español (es) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fes+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | فارسی (fa) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffa+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Suomi (fi) | ■■■■■■■■■・ 91% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffi+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Français (fr) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Français (fr) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Ffr+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | עברית (he) | ■■■■・・・・・・ 41% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhe+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Magyar (hu) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fhu+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Bahasa Indonesia (id) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fid+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | @@ -154,7 +154,7 @@ See the [repository dedicated to those extensions](https://github.com/FreshRSS/E | Latviešu (lv) | ■■■■■■■■・・ 81% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Flv+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Nederlands (nl) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fnl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Occitan (oc) | ■■■■■■■・・・ 73% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Foc+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | -| Polski (pl) | ■■■■■■■■■■ 100% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | +| Polski (pl) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpl+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Português (Brasil) (pt-BR) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-BR+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Português (Portugal) (pt-PT) | ■■■■■■■■■・ 99% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fpt-PT+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | | Русский (ru) | ■■■■■■■■■・ 98% | [contribute](https://github.com/search?q=repo%3AFreshRSS%2FFreshRSS+path%3Aapp%2Fi18n%2Fru+%2F%28TODO%7CDIRTY%29%28+-+.%2A%29%3F%24%2F) | diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 0bb2c4851..fe7e4de30 100644 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -429,7 +429,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { FreshRSS_View::appendScript(Minz_Url::display('/scripts/draggable.js?' . @filemtime(PUBLIC_PATH . '/scripts/draggable.js'))); if (Minz_Request::isPost()) { - /** @var array $params */ $params = Minz_Request::paramArray('queries'); @@ -512,9 +512,29 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { if (!empty($params['get']) && is_string($params['get'])) { $queryParams['get'] = $params['get']; } - if (!empty($params['order']) && is_string($params['order'])) { + // Order direction may arrive on its own when bookmarking the current view. + if (is_string($params['order'] ?? null) && in_array($params['order'], ['ASC', 'DESC'], true)) { $queryParams['order'] = $params['order']; } + // The query form submits a combined sort value (e.g. 'date_desc' or 'rand'); + // bookmarking the current view passes the sort field on its own instead. + $sorting = $params['sort'] ?? ''; + if (is_string($sorting) && $sorting !== '') { + if ($sorting === 'rand') { + $sortField = 'rand'; + } elseif (str_ends_with($sorting, '_asc')) { + $queryParams['order'] = 'ASC'; + $sortField = substr($sorting, 0, -strlen('_asc')); + } elseif (str_ends_with($sorting, '_desc')) { + $queryParams['order'] = 'DESC'; + $sortField = substr($sorting, 0, -strlen('_desc')); + } else { + $sortField = $sorting; + } + if (in_array($sortField, ['id', 'c.name', 'date', 'f.name', 'length', 'link', 'title', 'rand'], true)) { + $queryParams['sort'] = $sortField; + } + } if (!empty($params['search']) && is_string($params['search'])) { // Search must be as plain text to be XML-encoded or URL-encoded depending on the situation $queryParams['search'] = htmlspecialchars_decode($params['search'], ENT_QUOTES); @@ -608,7 +628,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { $queries = FreshRSS_Context::userConf()->queries; $id = empty($queries) ? 0 : (max(array_keys($queries)) + 1); - /** @var array{get?:string,name?:string,order?:string,search?:string,state?:int,shareRss?:bool,shareOpml?:bool,description?:string,imageUrl?:string} $params */ + /** @var array{get?:string,name?:string,order?:string,sort?:string,search?:string,state?:int,shareRss?:bool,shareOpml?:bool,description?:string,imageUrl?:string} $params */ $params = Minz_Request::paramArray('query') ?: array_filter($_GET, 'is_string', ARRAY_FILTER_USE_KEY); $name = ($params['name'] ?? '') ?: _t('conf.query.number', $id + 1); $queryParams = []; @@ -616,9 +636,29 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { if (is_string($params['get'] ?? null)) { $queryParams['get'] = $params['get']; } - if (is_string($params['order'] ?? null)) { + // Order direction may arrive on its own when bookmarking the current view. + if (is_string($params['order'] ?? null) && in_array($params['order'], ['ASC', 'DESC'], true)) { $queryParams['order'] = $params['order']; } + // The query form submits a combined sort value (e.g. 'date_desc' or 'rand'); + // bookmarking the current view passes the sort field on its own instead. + $sorting = $params['sort'] ?? ''; + if (is_string($sorting) && $sorting !== '') { + if ($sorting === 'rand') { + $sortField = 'rand'; + } elseif (str_ends_with($sorting, '_asc')) { + $queryParams['order'] = 'ASC'; + $sortField = substr($sorting, 0, -strlen('_asc')); + } elseif (str_ends_with($sorting, '_desc')) { + $queryParams['order'] = 'DESC'; + $sortField = substr($sorting, 0, -strlen('_desc')); + } else { + $sortField = $sorting; + } + if (in_array($sortField, ['id', 'c.name', 'date', 'f.name', 'length', 'link', 'title', 'rand'], true)) { + $queryParams['sort'] = $sortField; + } + } if (is_string($params['search'] ?? null)) { // Search must be as plain text to be XML-encoded or URL-encoded depending on the situation $queryParams['search'] = htmlspecialchars_decode($params['search'], ENT_QUOTES); diff --git a/app/Models/UserQuery.php b/app/Models/UserQuery.php index d41adbb85..8607d3372 100644 --- a/app/Models/UserQuery.php +++ b/app/Models/UserQuery.php @@ -15,6 +15,7 @@ class FreshRSS_UserQuery { /** XML-encoded name */ private string $name = ''; private string $order = ''; + private string $sort = ''; private readonly FreshRSS_BooleanSearch $search; private int $state = 0; private string $url = ''; @@ -45,7 +46,7 @@ class FreshRSS_UserQuery { } /** - * @param array{get?:string,name?:string,order?:string,search?:string,state?:int,url?:string,token?:string, + * @param array{get?:string,name?:string,order?:string,sort?:string,search?:string,state?:int,url?:string,token?:string, * shareRss?:bool,shareOpml?:bool,includeUserLabels?:bool,excludeArticleTags?:bool,userLabelPrefix?:string, * publishLabelsInsteadOfTags?:bool,description?:string,imageUrl?:string} $query * @param array $categories @@ -72,6 +73,9 @@ class FreshRSS_UserQuery { if (isset($query['order'])) { $this->order = $query['order']; } + if (isset($query['sort'])) { + $this->sort = $query['sort']; + } if (empty($query['url'])) { if (!empty($query)) { $link = $query; @@ -136,7 +140,7 @@ class FreshRSS_UserQuery { /** * Convert the current object to an array. * - * @return array{get?:string,name?:string,order?:string,search?:string, + * @return array{get?:string,name?:string,order?:string,sort?:string,search?:string, * state?:int,url?:string,token?:string,shareRss?:bool,shareOpml?:bool, * includeUserLabels?:bool,excludeArticleTags?:bool,userLabelPrefix?:string,description?:string,imageUrl?:string} */ @@ -145,6 +149,7 @@ class FreshRSS_UserQuery { 'get' => $this->get, 'name' => $this->name, 'order' => $this->order, + 'sort' => $this->sort, 'search' => $this->search->toString(expandUserQueries: false), 'state' => $this->state, 'url' => $this->url, @@ -238,6 +243,9 @@ class FreshRSS_UserQuery { if ($this->order !== '' && $this->order !== FreshRSS_Context::userConf()->sort_order) { return true; } + if ($this->sort !== '' && $this->sort !== FreshRSS_Context::userConf()->sort) { + return true; + } return false; } @@ -268,6 +276,10 @@ class FreshRSS_UserQuery { return $this->order ?: FreshRSS_Context::userConf()->sort_order; } + public function getSort(): string { + return $this->sort ?: FreshRSS_Context::userConf()->sort; + } + public function getSearch(): FreshRSS_BooleanSearch { return $this->search; } @@ -394,9 +406,9 @@ class FreshRSS_UserQuery { /** * Remove queries where $get is appearing. * @param string $get the get attribute which should be removed. - * @param array $queries an array of queries. - * @return array without queries where $get is appearing. */ public static function remove_query_by_get(string $get, array $queries): array { diff --git a/app/i18n/ar/conf.php b/app/i18n/ar/conf.php index 64c55b162..c2aed3854 100644 --- a/app/i18n/ar/conf.php +++ b/app/i18n/ar/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'العرض حسب الخلاصة', 'include_article_tags_label' => 'تضمين وسوم المقالات من الخلاصات', 'include_user_labels_label' => 'تضمين تسميات المستخدم، مع البادئة:', - 'order' => 'الفرز حسب التاريخ', + 'order' => 'Sort by', // TODO 'search' => 'التعبير', 'shareOpml' => 'تفعيل المشاركة عبر OPML للتصنيفات والخلاصات المقابلة', 'shareRss' => 'تفعيل المشاركة عبر HTML & RSS', diff --git a/app/i18n/az/conf.php b/app/i18n/az/conf.php index 53962e7cc..b1f5b5c84 100644 --- a/app/i18n/az/conf.php +++ b/app/i18n/az/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Lentə görə göstər', 'include_article_tags_label' => 'Lentlərdən gələn məqalə etiketlərini daxil et', 'include_user_labels_label' => 'İstifadəçi etiketlərini daxil et, prefiks ilə:', - 'order' => 'Tarixə görə sırala', + 'order' => 'Sort by', // TODO 'search' => 'İfadə', 'shareOpml' => 'Uyğun kateqoriya və lentlərin OPML ilə paylaşılmasını aktivləşdir', 'shareRss' => 'HTML & RSS ilə paylaşmanı aktivləşdir', diff --git a/app/i18n/cs/conf.php b/app/i18n/cs/conf.php index 3a98a1ee2..1c422f7de 100644 --- a/app/i18n/cs/conf.php +++ b/app/i18n/cs/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Zobrazit podle kanálu', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Seřadit podle data', + 'order' => 'Sort by', // TODO 'search' => 'Výraz', 'shareOpml' => 'Povolit sdílení příslušných kategorií a kanálů pomocí OPML', 'shareRss' => 'Povolit sdílení pomocí HTML & RSS', diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php index 701fd1c38..620ba88ee 100644 --- a/app/i18n/de/conf.php +++ b/app/i18n/de/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Nach Feed filtern', 'include_article_tags_label' => 'Artikel-Tags aus den Feeds berücksichtigen', 'include_user_labels_label' => 'Eigene Labels berücksichtigen, mit Präfix:', - 'order' => 'Nach Datum sortieren', + 'order' => 'Sort by', // TODO 'search' => 'Suchbegriff', 'shareOpml' => 'Teilen via OPML mit zugehörigen Kategorien und Feeds aktivieren', 'shareRss' => 'Teilen via HTML & RSS aktivieren', diff --git a/app/i18n/el/conf.php b/app/i18n/el/conf.php index e9cd5f086..924448d99 100644 --- a/app/i18n/el/conf.php +++ b/app/i18n/el/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Προβολή ανά ροή', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Ταξινόμηση κατά ημερομηνία', + 'order' => 'Sort by', // TODO 'search' => 'Έκφραση', 'shareOpml' => 'Ενεργοποίηση κοινοποίησης μέσω OPML των αντίστοιχων κατηγοριών και ροών', 'shareRss' => 'Ενεργοποίηση κοινοποίησης μέσω HTML & RSS', diff --git a/app/i18n/en-US/conf.php b/app/i18n/en-US/conf.php index 3609cfbe0..a7b60212f 100644 --- a/app/i18n/en-US/conf.php +++ b/app/i18n/en-US/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Display by feed', // IGNORE 'include_article_tags_label' => 'Include article tags from feeds', // IGNORE 'include_user_labels_label' => 'Include user labels, with prefix:', // IGNORE - 'order' => 'Sort by date', // IGNORE + 'order' => 'Sort by', // IGNORE 'search' => 'Expression', // IGNORE 'shareOpml' => 'Enable sharing by OPML of corresponding categories and feeds', // IGNORE 'shareRss' => 'Enable sharing by HTML & RSS', // IGNORE diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php index 7250b4e4a..f3a6382cc 100644 --- a/app/i18n/en/conf.php +++ b/app/i18n/en/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Display by feed', 'include_article_tags_label' => 'Include article tags from feeds', 'include_user_labels_label' => 'Include user labels, with prefix:', - 'order' => 'Sort by date', + 'order' => 'Sort by', 'search' => 'Expression', 'shareOpml' => 'Enable sharing by OPML of corresponding categories and feeds', 'shareRss' => 'Enable sharing by HTML & RSS', diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php index 32151f2e7..192d77804 100644 --- a/app/i18n/es/conf.php +++ b/app/i18n/es/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Mostrar por fuente', 'include_article_tags_label' => 'Incluir etiquetas de artículos de los feeds', 'include_user_labels_label' => 'Incluir etiquetas del usuario, con el prefijo:', - 'order' => 'Ordenar por fecha', + 'order' => 'Sort by', // TODO 'search' => 'Expresión', 'shareOpml' => 'Permitir que OPML comparta las categorías y fuentes correspondientes', 'shareRss' => 'Permite compartir por HTML & RSS', diff --git a/app/i18n/fa/conf.php b/app/i18n/fa/conf.php index a989f864a..39afc08f3 100644 --- a/app/i18n/fa/conf.php +++ b/app/i18n/fa/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => ' نمایش با فید', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => ' مرتب سازی بر اساس تاریخ', + 'order' => 'Sort by', // TODO 'search' => ' بیان', 'shareOpml' => 'فعال‌سازی اشتراک‌گذاری دسته‌ها و فیدهای مربوطه با OPML', 'shareRss' => 'اشتراک‌گذاری RSS', diff --git a/app/i18n/fi/conf.php b/app/i18n/fi/conf.php index 5bbf2dd79..fb8d9dfec 100644 --- a/app/i18n/fi/conf.php +++ b/app/i18n/fi/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Näytä syötteen mukaan', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Lajittele päivämäärän mukaan', + 'order' => 'Sort by', // TODO 'search' => 'Lauseke', 'shareOpml' => 'Jaa kyselyä vastaavat luokat ja syötteet OPML-muodossa', 'shareRss' => 'Jaa HTML & RSS -muodossa', diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php index 63f345a46..8e606e648 100644 --- a/app/i18n/fr/conf.php +++ b/app/i18n/fr/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Afficher par flux', 'include_article_tags_label' => 'Inclure les tags des articles provenant des flux', 'include_user_labels_label' => 'Inclure les étiquettes utilisateur, avec le préfixe :', - 'order' => 'Tri par date', + 'order' => 'Trier par', 'search' => 'Expression', // IGNORE 'shareOpml' => 'Active le partage par OPML des catégories et flux correspondants', 'shareRss' => 'Active le partage par HTML & RSS', diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php index 74a26245f..4a4dc9759 100644 --- a/app/i18n/fr/gen.php +++ b/app/i18n/fr/gen.php @@ -208,7 +208,7 @@ return array( 'it' => 'Italiano', // IGNORE 'ja' => '日本語', // IGNORE 'ko' => '한국어', // IGNORE - 'lt' => 'Lietuvių', // TODO + 'lt' => 'Lietuvių', // IGNORE 'lv' => 'Latviešu', // IGNORE 'nl' => 'Nederlands', // IGNORE 'oc' => 'Occitan', // IGNORE diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php index f3bb130f2..eec27182b 100644 --- a/app/i18n/he/conf.php +++ b/app/i18n/he/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Display by feed', // TODO 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Sort by date', // TODO + 'order' => 'Sort by', // TODO 'search' => 'Expression', // TODO 'shareOpml' => 'Enable sharing by OPML of corresponding categories and feeds', // TODO 'shareRss' => 'Enable sharing by HTML & RSS', // TODO diff --git a/app/i18n/hu/conf.php b/app/i18n/hu/conf.php index 1c855d022..17c89ee79 100644 --- a/app/i18n/hu/conf.php +++ b/app/i18n/hu/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Rendezés hírforrás szerint', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Rendezés dátum szerint', + 'order' => 'Sort by', // TODO 'search' => 'Kifejezés', 'shareOpml' => 'Engedélyezze a megfelelő kategóriák és hírcsatornák OPML-alapú megosztását', 'shareRss' => 'Engedélyezze a HTML & RSS megosztást', diff --git a/app/i18n/id/conf.php b/app/i18n/id/conf.php index 1f5c37572..a379bfbe2 100644 --- a/app/i18n/id/conf.php +++ b/app/i18n/id/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Tampilkan berdasarkan umpan', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Urutkan berdasarkan tanggal', + 'order' => 'Sort by', // TODO 'search' => 'Ekspresi Pencarian', 'shareOpml' => 'Aktifkan berbagi melalui OPML dari kategori dan umpan terkait', 'shareRss' => 'Aktifkan berbagi melalui HTML & RSS', diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php index b08989a8e..aba16a69e 100644 --- a/app/i18n/it/conf.php +++ b/app/i18n/it/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Mostra per feed', 'include_article_tags_label' => 'Includi i tag degli articoli provenienti dai feed', 'include_user_labels_label' => 'Includi le etichette dell’utente, con prefisso:', - 'order' => 'Ordina per data', + 'order' => 'Sort by', // TODO 'search' => 'Espressione', 'shareOpml' => 'Abilita la condivisione di OPML di categorie e feed corrispondenti', 'shareRss' => 'Abilita la condivisione di HTML & RSS', diff --git a/app/i18n/ja/conf.php b/app/i18n/ja/conf.php index 8c7561ce2..10dd9aa0e 100644 --- a/app/i18n/ja/conf.php +++ b/app/i18n/ja/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'フィードごとに表示する', 'include_article_tags_label' => 'フィードの記事タグを含める', 'include_user_labels_label' => 'プレフィックスを付けてユーザーラベルを含める:', - 'order' => '日付ごとにソートする', + 'order' => 'Sort by', // TODO 'search' => '検索式', 'shareOpml' => 'カテゴリとフィードのOPMLによる共有を有効にする', 'shareRss' => 'HTMLとRSSによる共有を有効にする', diff --git a/app/i18n/ko/conf.php b/app/i18n/ko/conf.php index 6ed28d394..8f4022dce 100644 --- a/app/i18n/ko/conf.php +++ b/app/i18n/ko/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => '피드별로 표시', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => '날짜순으로 정렬', + 'order' => 'Sort by', // TODO 'search' => '정규 표현식', 'shareOpml' => '해당 카테고리와 피드에 대한 OPML 공유 활성화', 'shareRss' => 'HTML 및 RSS 공유 활성화', diff --git a/app/i18n/lt/conf.php b/app/i18n/lt/conf.php index 638256956..ec2457323 100644 --- a/app/i18n/lt/conf.php +++ b/app/i18n/lt/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Rodyti pagal kanalą', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Rikiuoti pagal datą', + 'order' => 'Sort by', // TODO 'search' => 'Išraiška', 'shareOpml' => 'Įjungti atitinkamų kategorijų ir kanalų bendrinimą per OPML', 'shareRss' => 'Įjungti bendrinimą per HTML ir RSS', diff --git a/app/i18n/lv/conf.php b/app/i18n/lv/conf.php index c7944d70c..30672c29a 100644 --- a/app/i18n/lv/conf.php +++ b/app/i18n/lv/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Rādīt pēc barotnes', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Kārtot pēc datuma', + 'order' => 'Sort by', // TODO 'search' => 'Izteiksme', 'shareOpml' => 'Iespējot dalīšanos, izmantojot OPML atbilstošajām kategorijām un barotnēm', 'shareRss' => 'Iespējojiet koplietošanu ar HTML & RSS', diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php index 6ec8e7338..06f86b740 100644 --- a/app/i18n/nl/conf.php +++ b/app/i18n/nl/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Weergeven op feed', 'include_article_tags_label' => 'Artikel-tags van feeds opnemen', 'include_user_labels_label' => 'Gebruikerslabels opnemen, met voorvoegsel:', - 'order' => 'Sorteren op datum', + 'order' => 'Sort by', // TODO 'search' => 'Expressie', 'shareOpml' => 'Via OPML delen van bijbehorende categorieën en feeds aanzetten', 'shareRss' => 'Via HTML & RSS delen aanzetten', diff --git a/app/i18n/oc/conf.php b/app/i18n/oc/conf.php index 252507af2..4eeb5447c 100644 --- a/app/i18n/oc/conf.php +++ b/app/i18n/oc/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Afichatge per flux', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Triar per data', + 'order' => 'Sort by', // TODO 'search' => 'Expression', // IGNORE 'shareOpml' => 'Enable sharing by OPML of corresponding categories and feeds', // TODO 'shareRss' => 'Enable sharing by HTML & RSS', // TODO diff --git a/app/i18n/pl/conf.php b/app/i18n/pl/conf.php index 854ae6709..c39c71a03 100644 --- a/app/i18n/pl/conf.php +++ b/app/i18n/pl/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Według kanału', 'include_article_tags_label' => 'Uwzględnij tagi wiadomości z kanałów', 'include_user_labels_label' => 'Uwzględnij etykiety użytkownika z prefiksem:', - 'order' => 'Sortowanie wg daty', + 'order' => 'Sort by', // TODO 'search' => 'Wyrażenie', 'shareOpml' => 'Włącz udostępnianie OPML-ów zawierających kategorie i kanały', 'shareRss' => 'Włącz udostępnianie przez HTML i RSS', diff --git a/app/i18n/pt-BR/conf.php b/app/i18n/pt-BR/conf.php index 35d156202..10d40f4b6 100644 --- a/app/i18n/pt-BR/conf.php +++ b/app/i18n/pt-BR/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Exibir por feed', 'include_article_tags_label' => 'Incluir tags dos artigos dos feeds', 'include_user_labels_label' => 'Incluir rótulos do usuário, com prefixo:', - 'order' => 'Ordenar por data', + 'order' => 'Sort by', // TODO 'search' => 'Expressão', 'shareOpml' => 'Habilita o compartilhamento por OPML de categorias e feeds correspondentes', 'shareRss' => 'Habilita o compartilhamento por HTML & RSS', diff --git a/app/i18n/pt-PT/conf.php b/app/i18n/pt-PT/conf.php index 6aa229160..8415f27af 100644 --- a/app/i18n/pt-PT/conf.php +++ b/app/i18n/pt-PT/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Mostrar por feed', 'include_article_tags_label' => 'Incluir tags de artigos dos feeds', 'include_user_labels_label' => 'Incluir rótulos de utilizador, com o prefixo:', - 'order' => 'Ordenar por data', + 'order' => 'Sort by', // TODO 'search' => 'Expressão', 'shareOpml' => 'Ativar a partilha por OPML de categorias e feeds correspondentes', 'shareRss' => 'Ativar a partilha por HTML e RSS', diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php index 863a5916a..bb4cc7de5 100644 --- a/app/i18n/ru/conf.php +++ b/app/i18n/ru/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Отображение по ленте', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Сортировать по дате', + 'order' => 'Sort by', // TODO 'search' => 'Выражение', 'shareOpml' => 'Включить общий доступ с помощью OPML к соответствующим категориям и лентам', 'shareRss' => 'Включить общий доступ с помощью HTML & RSS', diff --git a/app/i18n/sk/conf.php b/app/i18n/sk/conf.php index ff9099817..8f0a55362 100644 --- a/app/i18n/sk/conf.php +++ b/app/i18n/sk/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Zobraziť podľa kanála', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Zobraziť podľa dátumu', + 'order' => 'Sort by', // TODO 'search' => 'Výraz', 'shareOpml' => 'Povoliť zdieľanie prostredníctvom OPML zodpovedajúdich kategórií a kanálov', 'shareRss' => 'Povoliť zdieľanie prostredníctvom HTML & RSS', diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php index 5279e298c..31dd70315 100644 --- a/app/i18n/tr/conf.php +++ b/app/i18n/tr/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Beslemeye göre göster', 'include_article_tags_label' => 'Beslemelerden gelen makale etiketlerini dahil et', 'include_user_labels_label' => 'Kullanıcı etiketlerini şu ön ekle dahil et:', - 'order' => 'Tarihe göre sırala', + 'order' => 'Sort by', // TODO 'search' => 'İfade', 'shareOpml' => 'İlgili kategori ve beslemelerin OPML ile paylaşımını etkinleştir', 'shareRss' => 'HTML ve RSS ile paylaşımı etkinleştir', diff --git a/app/i18n/uk/conf.php b/app/i18n/uk/conf.php index 57d1d6fee..2cb22441c 100644 --- a/app/i18n/uk/conf.php +++ b/app/i18n/uk/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => 'Показати стрічку', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => 'Впорядкувати за датою', + 'order' => 'Sort by', // TODO 'search' => 'Вираз', 'shareOpml' => 'Увімкнути OPML-поширення відповідних категорій і стрічок', 'shareRss' => 'Увімкнути поширення в форматі HTML і RSS', diff --git a/app/i18n/zh-CN/conf.php b/app/i18n/zh-CN/conf.php index aa13fca31..07d645e63 100644 --- a/app/i18n/zh-CN/conf.php +++ b/app/i18n/zh-CN/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => '按订阅源显示', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => '按日期排序', + 'order' => 'Sort by', // TODO 'search' => '表达式', 'shareOpml' => '启用相应类别和 feed 的 OPML 分享', 'shareRss' => '启用 HTML 和 RSS 分享', diff --git a/app/i18n/zh-TW/conf.php b/app/i18n/zh-TW/conf.php index 025890551..fef01ae64 100644 --- a/app/i18n/zh-TW/conf.php +++ b/app/i18n/zh-TW/conf.php @@ -203,7 +203,7 @@ return array( 'feeds' => '按訂閱源顯示', 'include_article_tags_label' => 'Include article tags from feeds', // TODO 'include_user_labels_label' => 'Include user labels, with prefix:', // TODO - 'order' => '按日期排序', + 'order' => 'Sort by', // TODO 'search' => '表達式', 'shareOpml' => '啟用透過對應類別和訂閱源的 OPML 分享', 'shareRss' => '啟用透過 HTML 分享 & RSS', diff --git a/app/views/configure/queries.phtml b/app/views/configure/queries.phtml index 1130c7614..8849baa9f 100644 --- a/app/views/configure/queries.phtml +++ b/app/views/configure/queries.phtml @@ -117,12 +117,27 @@
- +
- - - + + + + + + + + + + + + + + + + +
@@ -179,6 +194,7 @@ + hasParameters()) { ?> @@ -203,13 +219,8 @@
  • getState()] ?? '' ?>
  • - getOrder() !== '') { ?> -
  • getOrder()) { - 'ASC' => _t('conf.query.order_asc'), - 'DESC' => _t('conf.query.order_desc'), - default => '', - } ?>
  • - + getSort(); $sortCombined = $qSort === 'rand' ? 'rand' : $qSort . '_' . strtolower($query->getOrder()); ?> +
  • getGet() !== '') { ?>
  • getGetType()) { diff --git a/app/views/helpers/configure/query.phtml b/app/views/helpers/configure/query.phtml index 75147d14d..181532582 100644 --- a/app/views/helpers/configure/query.phtml +++ b/app/views/helpers/configure/query.phtml @@ -161,13 +161,32 @@ + query->getSort(); + $querySortCombined = $querySort === 'rand' ? 'rand' : $querySort . '_' . strtolower($this->query->getOrder()); + ?>
    - +
    - - - + + + + + + + + + + + + + + + + +
    diff --git a/p/api/query.php b/p/api/query.php index c843a2436..73d755e8d 100644 --- a/p/api/query.php +++ b/p/api/query.php @@ -96,6 +96,9 @@ foreach (FreshRSS_Context::userConf()->queries as $raw_query) { if (Minz_Request::paramString('order', plaintext: true) === '') { Minz_Request::_param('order', $query->getOrder()); } + if (Minz_Request::paramString('sort', plaintext: true) === '') { + Minz_Request::_param('sort', $query->getSort()); + } Minz_Request::_param('state', (string)$query->getState()); $search = $query->getSearch()->toString(); diff --git a/tests/app/Models/UserQueryTest.php b/tests/app/Models/UserQueryTest.php index 93f2d1a61..4dd69ba24 100644 --- a/tests/app/Models/UserQueryTest.php +++ b/tests/app/Models/UserQueryTest.php @@ -88,6 +88,13 @@ class UserQueryTest extends TestCase { self::assertSame($order, $user_query->getOrder()); } + public static function test__construct_whenSort_storesSort(): void { + $sort = 'title'; + $query = ['sort' => $sort]; + $user_query = new FreshRSS_UserQuery($query, [], []); + self::assertSame($sort, $user_query->getSort()); + } + public static function test__construct_whenState_storesState(): void { $state = FreshRSS_Entry::STATE_NOT_READ | FreshRSS_Entry::STATE_FAVORITE; $query = ['state' => $state]; @@ -122,6 +129,12 @@ class UserQueryTest extends TestCase { self::assertSame($query, $user_query->toArray()); } + public static function testToArray_whenSort_returnsSort(): void { + $query = ['sort' => 'date']; + $user_query = new FreshRSS_UserQuery($query, [], []); + self::assertSame('date', $user_query->toArray()['sort'] ?? null); + } + public static function testHasSearch_whenSearch_returnsTrue(): void { $query = ['search' => 'some search']; $user_query = new FreshRSS_UserQuery($query, [], []);