From cce1089e10740bbf6a7ee38fc9227cfcd09f2aaf Mon Sep 17 00:00:00 2001 From: "J. King" Date: Tue, 2 Apr 2019 19:58:35 -0400 Subject: [PATCH] Handle edge case with folder 0 Folder 0 (the root folder) is a valid, though nonsensical selection: using it as a positive option is the same as not using the option at all, and using it as a negative option necessarily yields an empty set. However, it can in some contexts be validly specified, and so it should be handled consistently. It had not been previously, but is now. --- lib/Context/ExclusionContext.php | 1 + lib/Database.php | 4 ++-- tests/cases/Database/SeriesArticle.php | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Context/ExclusionContext.php b/lib/Context/ExclusionContext.php index 63cc97d..7cf45cb 100644 --- a/lib/Context/ExclusionContext.php +++ b/lib/Context/ExclusionContext.php @@ -49,6 +49,7 @@ class ExclusionContext { } public function __clone() { + // if the context was cloned because its parent was cloned, change the parent to the clone if ($this->parent) { $t = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT, 2)[1]; if (($t['object'] ?? null) instanceof self && $t['function'] === "__clone") { diff --git a/lib/Database.php b/lib/Database.php index 404f451..1173ae6 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -1461,13 +1461,13 @@ class Database { } if ($context->folder()) { // add a common table expression to list the folder and its children so that we select from the entire subtree - $q->setCTE("folders(folder)", "SELECT ? union select id from arsse_folders join folders on parent = folder", "int", $context->folder); + $q->setCTE("folders(folder)", "SELECT ? union select id from arsse_folders join folders on coalesce(parent,0) = folder", "int", $context->folder); // limit subscriptions to the listed folders $q->setWhere("coalesce(arsse_subscriptions.folder,0) in (select folder from folders)"); } 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 parent = folder", "int", $context->not->folder); + $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)"); } diff --git a/tests/cases/Database/SeriesArticle.php b/tests/cases/Database/SeriesArticle.php index 694aec5..31dcf96 100644 --- a/tests/cases/Database/SeriesArticle.php +++ b/tests/cases/Database/SeriesArticle.php @@ -424,6 +424,7 @@ trait SeriesArticle { return [ 'Blank context' => [new Context, [1,2,3,4,5,6,7,8,19,20]], '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]], 'Shallow folder' => [(new Context)->folderShallow(1), [5,6]], @@ -506,6 +507,7 @@ trait SeriesArticle { 'Excluding tag ID 5' => [(new Context)->not->tag(5), [1,2,3,4,5,6]], '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), []], ]; }