diff --git a/lib/topic_query.rb b/lib/topic_query.rb index 49f02f6ffd1..86c126f2fe4 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -677,15 +677,18 @@ class TopicQuery else sql = <<~SQL categories.id IN ( - SELECT c2.id FROM categories c2 WHERE c2.parent_category_id = :category_id - UNION ALL - SELECT :category_id - ) AND - topics.id NOT IN ( - SELECT c3.topic_id FROM categories c3 WHERE c3.parent_category_id = :category_id AND c3.topic_id IS NOT NULL + WITH RECURSIVE subcategories AS ( + SELECT :category_id id, 1 depth + UNION + SELECT categories.id, (subcategories.depth + 1) depth + FROM categories + JOIN subcategories ON subcategories.id = categories.parent_category_id + WHERE subcategories.depth < :max_category_nesting ) + SELECT subcategories.id FROM subcategories + ) AND (categories.id = :category_id OR topics.id != categories.topic_id) SQL - result = result.where(sql, category_id: category_id) + result = result.where(sql, category_id: category_id, max_category_nesting: SiteSetting.max_category_nesting) end result = result.references(:categories) diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 558d4175464..b4c5cd93458 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -153,6 +153,7 @@ describe TopicQuery do context 'subcategories' do let!(:subcategory) { Fabricate(:category_with_definition, parent_category_id: category.id) } + let(:subsubcategory) { Fabricate(:category_with_definition, parent_category_id: subcategory.id) } it "works with subcategories" do expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(1) @@ -160,6 +161,23 @@ describe TopicQuery do expect(TopicQuery.new(moderator, category: category.id, no_subcategories: true).list_latest.topics.size).to eq(1) end + it "works with subsubcategories" do + SiteSetting.max_category_nesting = 3 + + Fabricate(:topic, category: category) + Fabricate(:topic, category: subcategory) + Fabricate(:topic, category: subsubcategory) + + SiteSetting.max_category_nesting = 2 + expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(3) + expect(TopicQuery.new(moderator, category: subcategory.id).list_latest.topics.size).to eq(3) + expect(TopicQuery.new(moderator, category: subsubcategory.id).list_latest.topics.size).to eq(2) + + SiteSetting.max_category_nesting = 3 + expect(TopicQuery.new(moderator, category: category.id).list_latest.topics.size).to eq(4) + expect(TopicQuery.new(moderator, category: subcategory.id).list_latest.topics.size).to eq(3) + expect(TopicQuery.new(moderator, category: subsubcategory.id).list_latest.topics.size).to eq(2) + end end end