diff --git a/lib/Database.php b/lib/Database.php index 1173ae67..459f4676 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -1465,12 +1465,26 @@ class Database { // limit subscriptions to the listed folders $q->setWhere("coalesce(arsse_subscriptions.folder,0) in (select folder from folders)"); } + if ($context->folders()) { + list($inClause, $inTypes, $inValues) = $this->generateIn($context->folders, "int"); + // add a common table expression to list the folders and their children so that we select from the entire subtree + $q->setCTE("folders_multi(folder)", "SELECT id as folder from (select id from (select 0 as id union select id from arsse_folders where owner = ?) as f where id in ($inClause)) as folders_multi union select id from arsse_folders join folders_multi on coalesce(parent,0) = folder", ["str", $inTypes], [$user, $inValues]); + // limit subscriptions to the listed folders + $q->setWhere("coalesce(arsse_subscriptions.folder,0) in (select folder from folders_multi)"); + } if ($context->not->folder()) { // add a common table expression to list the folder and its children so that we exclude from the entire subtree $q->setCTE("folders_excluded(folder)", "SELECT ? union select id from arsse_folders join folders_excluded on coalesce(parent,0) = folder", "int", $context->not->folder); // excluded any subscriptions in the listed folders $q->setWhereNot("coalesce(arsse_subscriptions.folder,0) in (select folder from folders_excluded)"); } + if ($context->not->folders()) { + list($inClause, $inTypes, $inValues) = $this->generateIn($context->not->folders, "int"); + // add a common table expression to list the folders and their children so that we select from the entire subtree + $q->setCTE("folders_multi_excluded(folder)", "SELECT id as folder from (select id from (select 0 as id union select id from arsse_folders where owner = ?) as f where id in ($inClause)) as folders_multi_excluded union select id from arsse_folders join folders_multi_excluded on coalesce(parent,0) = folder", ["str", $inTypes], [$user, $inValues]); + // limit subscriptions to the listed folders + $q->setWhereNot("coalesce(arsse_subscriptions.folder,0) in (select folder from folders_multi_excluded)"); + } // handle text-matching context options $options = [ "titleTerms" => ["arsse_articles.title"], diff --git a/tests/cases/Database/SeriesArticle.php b/tests/cases/Database/SeriesArticle.php index 31dcf961..17b0ece3 100644 --- a/tests/cases/Database/SeriesArticle.php +++ b/tests/cases/Database/SeriesArticle.php @@ -426,8 +426,10 @@ trait SeriesArticle { 'Folder tree' => [(new Context)->folder(1), [5,6,7,8]], 'Entire folder tree' => [(new Context)->folder(0), [1,2,3,4,5,6,7,8,19,20]], 'Leaf folder' => [(new Context)->folder(6), [7,8]], - 'Root folder only' => [(new Context)->folderShallow(0), [1,2,3,4]], + 'Multiple folder trees' => [(new Context)->folders([1,5]), [5,6,7,8,19,20]], + 'Multiple folder trees including root' => [(new Context)->folders([0,1,5]), [1,2,3,4,5,6,7,8,19,20]], 'Shallow folder' => [(new Context)->folderShallow(1), [5,6]], + 'Root folder only' => [(new Context)->folderShallow(0), [1,2,3,4]], 'Multiple shallow folders' => [(new Context)->foldersShallow([1,6]), [5,6,7,8]], 'Subscription' => [(new Context)->subscription(5), [19,20]], 'Multiple subscriptions' => [(new Context)->subscriptions([4,5]), [7,8,19,20]], @@ -508,6 +510,8 @@ trait SeriesArticle { 'Excluding tag "Technology"' => [(new Context)->not->tagName("Technology"), [1,2,3,4,19,20]], 'Excluding tag "Politics"' => [(new Context)->not->tagName("Politics"), [1,2,3,4,5,6]], 'Excluding entire folder tree' => [(new Context)->not->folder(0), []], + 'Excluding multiple folder trees' => [(new Context)->not->folders([1,5]), [1,2,3,4]], + 'Excluding multiple folder trees including root' => [(new Context)->not->folders([0,1,5]), []], ]; }