diff --git a/lib/topic_query.rb b/lib/topic_query.rb index f5c2ab12962..f52c6977469 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -346,16 +346,22 @@ class TopicQuery end def self.tracked_filter(list, user_id) + tracked_category_ids_sql = <<~SQL + SELECT cd.category_id FROM category_users cd + WHERE cd.user_id = :user_id AND cd.notification_level >= :tracking + SQL + + has_sub_sub_categories = SiteSetting.max_category_nesting == 3 + sql = +<<~SQL topics.category_id IN ( - SELECT cu.category_id FROM category_users cu - WHERE cu.user_id = :user_id AND cu.notification_level >= :tracking - ) - OR topics.category_id IN ( - SELECT c.id FROM categories c WHERE c.parent_category_id IN ( - SELECT cd.category_id FROM category_users cd - WHERE cd.user_id = :user_id AND cd.notification_level >= :tracking - ) + SELECT + c.id + FROM categories c + #{has_sub_sub_categories ? "LEFT JOIN categories parent_categories ON parent_categories.id = c.parent_category_id" : ""} + WHERE (c.parent_category_id IS NULL AND c.id IN (#{tracked_category_ids_sql})) + OR c.parent_category_id IN (#{tracked_category_ids_sql}) + #{has_sub_sub_categories ? "OR (parent_categories.id IS NOT NULL AND parent_categories.parent_category_id IN (#{tracked_category_ids_sql}))" : ""} ) SQL diff --git a/spec/lib/topic_query_spec.rb b/spec/lib/topic_query_spec.rb index ec59e77b83f..66a12cb294c 100644 --- a/spec/lib/topic_query_spec.rb +++ b/spec/lib/topic_query_spec.rb @@ -164,7 +164,7 @@ describe TopicQuery do SiteSetting.tagging_enabled = true tag = Fabricate(:tag) - Fabricate(:topic, tags: [tag]) + topic = Fabricate(:topic, tags: [tag]) topic2 = Fabricate(:topic) query = TopicQuery.new(user, filter: 'tracked').list_latest @@ -183,26 +183,38 @@ describe TopicQuery do ) query = TopicQuery.new(user, filter: 'tracked').list_latest - expect(query.topics.length).to eq(1) + + expect(query.topics.map(&:id)).to contain_exactly(topic.id) cu.update!(notification_level: NotificationLevels.all[:tracking]) query = TopicQuery.new(user, filter: 'tracked').list_latest - expect(query.topics.length).to eq(2) + + expect(query.topics.map(&:id)).to contain_exactly(topic.id, topic2.id) # includes subcategories of tracked categories - parentcat = Fabricate(:category) - subcat = Fabricate(:category, parent_category_id: parentcat.id) - topic3 = Fabricate(:topic, category_id: subcat.id) + parent_category = Fabricate(:category) + sub_category = Fabricate(:category, parent_category_id: parent_category.id) + topic3 = Fabricate(:topic, category_id: sub_category.id) CategoryUser.create!( - category_id: parentcat.id, + category_id: parent_category.id, user_id: user.id, notification_level: NotificationLevels.all[:tracking] ) query = TopicQuery.new(user, filter: 'tracked').list_latest - expect(query.topics.length).to eq(3) + + expect(query.topics.map(&:id)).to contain_exactly(topic.id, topic2.id, topic3.id) + + # includes sub-subcategories of tracked categories + SiteSetting.max_category_nesting = 3 + sub_sub_category = Fabricate(:category, parent_category_id: sub_category.id) + topic4 = Fabricate(:topic, category_id: sub_sub_category.id) + + query = TopicQuery.new(user, filter: 'tracked').list_latest + + expect(query.topics.map(&:id)).to contain_exactly(topic.id, topic2.id, topic3.id, topic4.id) end end