mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 05:44:53 +00:00
Added topmost folder to output of subscriptionList. Fixes #54
- Adjusted NCN handler to use the topmost folder for folderId; suppressed the actual folder so as not to pollute output with non-standard data - Updated tests
This commit is contained in:
parent
ba6b5dee85
commit
81419452b5
4 changed files with 42 additions and 23 deletions
|
@ -356,30 +356,42 @@ class Database {
|
||||||
|
|
||||||
public function subscriptionList(string $user, int $folder = null, int $id = null): Db\Result {
|
public function subscriptionList(string $user, int $folder = null, int $id = null): Db\Result {
|
||||||
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
if(!Data::$user->authorize($user, __FUNCTION__)) throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
|
||||||
// check to make sure the folder exists, if one is specified
|
// lay out the base query parts
|
||||||
|
$queryCTE = ["topmost(f_id,top) as (select id,id from arsse_folders where owner is ? and parent is null union select id,top from arsse_folders join topmost on parent=f_id)"];
|
||||||
|
$queryWhere = ["owner is ?"];
|
||||||
|
$queryTypes = ["str", "str", "str", "str"];
|
||||||
|
$queryValues = [$user, $this->dateFormatDefault, $user, $user];
|
||||||
|
if(!is_null($folder)) {
|
||||||
|
// if a folder is specified, make sure it exists
|
||||||
|
$this->folderValidateId($user, $folder);
|
||||||
|
// if it does exist, add a common table expression to list it and its children so that we select from the entire subtree
|
||||||
|
array_unshift($queryCTE, "folders(folder) as (SELECT ? union select id from arsse_folders join folders on parent is folder)");
|
||||||
|
// add a suitable WHERE condition and bindings
|
||||||
|
$queryWhere[] = "folder in (select folder from folders)";
|
||||||
|
array_unshift($queryTypes, "int");
|
||||||
|
array_unshift($queryValues, $folder);
|
||||||
|
}
|
||||||
|
if(!is_null($id)) {
|
||||||
|
// this condition facilitates the implementation of subscriptionPropertiesGet, which would otherwise have to duplicate the complex query
|
||||||
|
// if an ID is specified, add a suitable WHERE condition and bindings
|
||||||
|
$queryWhere[] = "arsse_subscriptions.id is ?";
|
||||||
|
$queryTypes[] = "int";
|
||||||
|
$queryValues[] = $id;
|
||||||
|
}
|
||||||
|
// stitch the query together
|
||||||
|
$queryCTE = "WITH RECURSIVE ".implode(", ", $queryCTE)." ";
|
||||||
|
$queryWhere = implode(" AND ", $queryWhere);
|
||||||
$query =
|
$query =
|
||||||
"SELECT
|
$queryCTE."SELECT
|
||||||
arsse_subscriptions.id,
|
arsse_subscriptions.id,
|
||||||
url,favicon,source,folder,pinned,err_count,err_msg,order_type,
|
url,favicon,source,folder,pinned,err_count,err_msg,order_type,
|
||||||
DATEFORMAT(?, added) as added,
|
DATEFORMAT(?, added) as added,
|
||||||
|
topmost.top as top_folder,
|
||||||
CASE WHEN arsse_subscriptions.title is not null THEN arsse_subscriptions.title ELSE arsse_feeds.title END as title,
|
CASE WHEN arsse_subscriptions.title is not null THEN arsse_subscriptions.title ELSE arsse_feeds.title END as title,
|
||||||
(SELECT count(*) from arsse_articles where feed is arsse_subscriptions.feed) - (SELECT count(*) from arsse_marks join arsse_articles on article = arsse_articles.id where owner is ? and feed is arsse_feeds.id and read is 1) as unread
|
(SELECT count(*) from arsse_articles where feed is arsse_subscriptions.feed) - (SELECT count(*) from arsse_marks join arsse_articles on article = arsse_articles.id where owner is ? and feed is arsse_feeds.id and read is 1) as unread
|
||||||
from arsse_subscriptions join arsse_feeds on feed = arsse_feeds.id where owner is ?";
|
from arsse_subscriptions join arsse_feeds on feed = arsse_feeds.id left join topmost on folder=f_id where $queryWhere order by pinned desc, title";
|
||||||
$queryOrder = "order by pinned desc, title";
|
// execute the query
|
||||||
$queryTypes = ["str", "str", "str"];
|
return $this->db->prepare($query, $queryTypes)->run($queryValues);
|
||||||
$queryValues = [$this->dateFormatDefault, $user, $user];
|
|
||||||
if(!is_null($folder)) {
|
|
||||||
$this->folderValidateId($user, $folder);
|
|
||||||
return $this->db->prepare(
|
|
||||||
"WITH RECURSIVE folders(folder) as (SELECT ? union select id from arsse_folders join folders on parent is folder) $query and folder in (select folder from folders) $queryOrder",
|
|
||||||
"int", $queryTypes
|
|
||||||
)->run($folder, $queryValues);
|
|
||||||
} else if(!is_null($id)) {
|
|
||||||
// this condition facilitates the implementation of subscriptionPropertiesGet, which would otherwise have to duplicate the complex query
|
|
||||||
return $this->db->prepare("$query and arsse_subscriptions.id is ? $queryOrder", $queryTypes, "int")->run($queryValues, $id);
|
|
||||||
} else {
|
|
||||||
return $this->db->prepare("$query $queryOrder", $queryTypes)->run($queryValues);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function subscriptionRemove(string $user, int $id): bool {
|
public function subscriptionRemove(string $user, int $id): bool {
|
||||||
|
|
|
@ -180,19 +180,21 @@ class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
||||||
protected function feedTranslate(array $feed, bool $overwrite = false): array {
|
protected function feedTranslate(array $feed, bool $overwrite = false): array {
|
||||||
// cast values
|
// cast values
|
||||||
$feed = $this->mapFieldTypes($feed, [
|
$feed = $this->mapFieldTypes($feed, [
|
||||||
'folder' => "int",
|
'top_folder' => "int",
|
||||||
'pinned' => "bool",
|
'pinned' => "bool",
|
||||||
]);
|
]);
|
||||||
// map fields to proper names
|
// map fields to proper names
|
||||||
$feed = $this->mapFieldNames($feed, [
|
$feed = $this->mapFieldNames($feed, [
|
||||||
'source' => "link",
|
'source' => "link",
|
||||||
'favicon' => "faviconLink",
|
'favicon' => "faviconLink",
|
||||||
'folder' => "folderId",
|
'top_folder' => "folderId",
|
||||||
'unread' => "unreadCount",
|
'unread' => "unreadCount",
|
||||||
'order_type' => "ordering",
|
'order_type' => "ordering",
|
||||||
'err_count' => "updateErrorCount",
|
'err_count' => "updateErrorCount",
|
||||||
'err_msg' => "lastUpdateError",
|
'err_msg' => "lastUpdateError",
|
||||||
], $overwrite);
|
], $overwrite);
|
||||||
|
// remove the true folder since the protocol does not support nesting
|
||||||
|
unset($feed['folder']);
|
||||||
return $feed;
|
return $feed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
|
||||||
'url' => 'http://example.com/news.atom',
|
'url' => 'http://example.com/news.atom',
|
||||||
'favicon' => 'http://example.com/favicon.png',
|
'favicon' => 'http://example.com/favicon.png',
|
||||||
'source' => 'http://example.com/',
|
'source' => 'http://example.com/',
|
||||||
'folder' => NULL,
|
'folder' => null,
|
||||||
|
'top_folder' => null,
|
||||||
'pinned' => 0,
|
'pinned' => 0,
|
||||||
'err_count' => 0,
|
'err_count' => 0,
|
||||||
'err_msg' => '',
|
'err_msg' => '',
|
||||||
|
@ -32,7 +33,8 @@ class TestNCNV1_2 extends \PHPUnit\Framework\TestCase {
|
||||||
'url' => 'http://example.org/news.atom',
|
'url' => 'http://example.org/news.atom',
|
||||||
'favicon' => 'http://example.org/favicon.png',
|
'favicon' => 'http://example.org/favicon.png',
|
||||||
'source' => 'http://example.org/',
|
'source' => 'http://example.org/',
|
||||||
'folder' => 8,
|
'folder' => 12,
|
||||||
|
'top_folder' => 8,
|
||||||
'pinned' => 1,
|
'pinned' => 1,
|
||||||
'err_count' => 0,
|
'err_count' => 0,
|
||||||
'err_msg' => '',
|
'err_msg' => '',
|
||||||
|
|
|
@ -189,6 +189,7 @@ trait SeriesSubscription {
|
||||||
'url' => "http://example.com/feed2",
|
'url' => "http://example.com/feed2",
|
||||||
'title' => "Eek",
|
'title' => "Eek",
|
||||||
'folder' => null,
|
'folder' => null,
|
||||||
|
'top_folder' => null,
|
||||||
'unread' => 4,
|
'unread' => 4,
|
||||||
'pinned' => 1,
|
'pinned' => 1,
|
||||||
'order_type' => 2,
|
'order_type' => 2,
|
||||||
|
@ -197,6 +198,7 @@ trait SeriesSubscription {
|
||||||
'url' => "http://example.com/feed3",
|
'url' => "http://example.com/feed3",
|
||||||
'title' => "Ook",
|
'title' => "Ook",
|
||||||
'folder' => 2,
|
'folder' => 2,
|
||||||
|
'top_folder' => 1,
|
||||||
'unread' => 2,
|
'unread' => 2,
|
||||||
'pinned' => 0,
|
'pinned' => 0,
|
||||||
'order_type' => 1,
|
'order_type' => 1,
|
||||||
|
@ -215,6 +217,7 @@ trait SeriesSubscription {
|
||||||
'url' => "http://example.com/feed3",
|
'url' => "http://example.com/feed3",
|
||||||
'title' => "Ook",
|
'title' => "Ook",
|
||||||
'folder' => 2,
|
'folder' => 2,
|
||||||
|
'top_folder' => 1,
|
||||||
'unread' => 2,
|
'unread' => 2,
|
||||||
'pinned' => 0,
|
'pinned' => 0,
|
||||||
'order_type' => 1,
|
'order_type' => 1,
|
||||||
|
|
Loading…
Reference in a new issue