diff --git a/docs/en/030_Supported_Protocols/005_Miniflux.md b/docs/en/030_Supported_Protocols/005_Miniflux.md index da52cb4..38ede1c 100644 --- a/docs/en/030_Supported_Protocols/005_Miniflux.md +++ b/docs/en/030_Supported_Protocols/005_Miniflux.md @@ -49,6 +49,8 @@ For convenience the patterns are tested after collapsing whitespace. Unlike Mini Nextcloud News' root folder and Tiny Tiny RSS' "Uncategorized" catgory are mapped to Miniflux's initial "All" category. This Miniflux category can be renamed, but it cannot be deleted. Attempting to do so will delete the child feeds it contains, but not the category itself. +Because the root folder does not existing in the database as a separate entity, it will always sort first when ordering by `category_id` or `category_title`. + # Interaction with nested categories Tiny Tiny RSS is unique in allowing newsfeeds to be grouped into categories nested to arbitrary depth. When newsfeeds are placed into nested categories, they simply appear in the top-level category when accessed via the Miniflux protocol. This does not affect OPML exports, where full nesting is preserved. diff --git a/lib/Database.php b/lib/Database.php index 62740d4..db6f087 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -1461,6 +1461,9 @@ class Database { 'guid' => "arsse_articles.guid", // The GUID of the article, as presented in the feed (NOTE: Picofeed actually provides a hash of the ID) 'fingerprint' => "arsse_articles.url_title_hash || ':' || arsse_articles.url_content_hash || ':' || arsse_articles.title_content_hash", // A combination of three hashes 'folder' => "coalesce(arsse_subscriptions.folder,0)", // The folder of the article's feed. This is mainly for use in WHERE clauses + 'top_folder' => "coalesce(folder_data.top,0)", // The top-most folder of the article's feed. This is mainly for use in WHERE clauses + 'folder_name' => "folder_data.name", // The name of the folder of the article's feed. This is mainly for use in WHERE clauses + 'top_folder_name' => "folder_data.top_name", // The name of the top-most folder of the article's feed. This is mainly for use in WHERE clauses 'subscription' => "arsse_subscriptions.id", // The article's parent subscription 'feed' => "arsse_subscriptions.feed", // The article's parent feed 'hidden' => "coalesce(arsse_marks.hidden,0)", // Whether the article is hidden @@ -1537,6 +1540,7 @@ class Database { from arsse_articles join arsse_subscriptions on arsse_subscriptions.feed = arsse_articles.feed and arsse_subscriptions.owner = ? join arsse_feeds on arsse_subscriptions.feed = arsse_feeds.id + left join folder_data on arsse_subscriptions.folder = folder_data.id left join arsse_marks on arsse_marks.subscription = arsse_subscriptions.id and arsse_marks.article = arsse_articles.id left join arsse_enclosures on arsse_enclosures.article = arsse_articles.id join ( @@ -1548,6 +1552,8 @@ class Database { ["str", "str"], [$user, $user] ); + $q->setCTE("topmost(f_id,top)", "SELECT id,id from arsse_folders where owner = ? and parent is null union all select id,top from arsse_folders join topmost on parent=f_id", ["str"], [$user]); + $q->setCTE("folder_data(id,name,top,top_name)", "SELECT f1.id, f1.name, top, f2.name from arsse_folders as f1 join topmost on f1.id = f_id join arsse_folders as f2 on f2.id = top"); $q->setLimit($context->limit, $context->offset); // handle the simple context options $options = [ @@ -1788,9 +1794,9 @@ class Database { $order = $col[1] ?? ""; $col = $col[0]; if ($order === "desc") { - $order = " desc"; + $order = " ".$this->db->sqlToken("desc"); } elseif ($order === "asc" || $order === "") { - $order = ""; + $order = " ".$this->db->sqlToken("asc"); } else { // column direction spec is bogus continue; diff --git a/lib/REST/Miniflux/V1.php b/lib/REST/Miniflux/V1.php index 5510bd2..ea72510 100644 --- a/lib/REST/Miniflux/V1.php +++ b/lib/REST/Miniflux/V1.php @@ -936,9 +936,9 @@ class V1 extends \JKingWeb\Arsse\REST\AbstractHandler { } elseif ($query['order'] === "published_at") { $order = ["modified_date".$desc]; } elseif ($query['order'] === "category_title") { - $order = []; // TODO + $order = ["top_folder_name".$desc]; } elseif ($query['order'] === "catgory_id") { - $order = []; //TODO + $order = ["top_folder".$desc]; } else { $order = []; } diff --git a/tests/cases/Database/SeriesArticle.php b/tests/cases/Database/SeriesArticle.php index 6302f5d..eace73a 100644 --- a/tests/cases/Database/SeriesArticle.php +++ b/tests/cases/Database/SeriesArticle.php @@ -408,8 +408,9 @@ trait SeriesArticle { ], ]; $this->fields = [ - "id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "edition", "edited_date", + "id", "subscription", "feed", "modified_date", "marked_date", "unread", "starred", "hidden", "edition", "edited_date", "url", "title", "subscription_title", "author", "guid", "published_date", "fingerprint", + "folder", "top_folder", "folder_name", "top_folder_name", "content", "media_url", "media_type", "note", ];