diff --git a/lib/discourse_tagging.rb b/lib/discourse_tagging.rb index 6aac1518881..fa70a4407af 100644 --- a/lib/discourse_tagging.rb +++ b/lib/discourse_tagging.rb @@ -379,13 +379,13 @@ module DiscourseTagging CATEGORY_RESTRICTIONS_SQL ||= <<~SQL category_restrictions AS ( - SELECT t.id as tag_id, ct.id as ct_id, ct.category_id as category_id + SELECT t.id as tag_id, ct.id as ct_id, ct.category_id as category_id, NULL AS category_tag_group_id FROM tags t INNER JOIN category_tags ct ON t.id = ct.tag_id /*and_name_like*/ UNION - SELECT t.id as tag_id, ctg.id as ctg_id, ctg.category_id as category_id + SELECT t.id as tag_id, ctg.id as ctg_id, ctg.category_id as category_id, ctg.tag_group_id AS category_tag_group_id FROM tags t INNER JOIN tag_group_memberships tgm ON tgm.tag_id = t.id /*and_name_like*/ INNER JOIN category_tag_groups ctg ON tgm.tag_group_id = ctg.tag_group_id @@ -458,7 +458,7 @@ module DiscourseTagging FROM tags t INNER JOIN tag_group_restrictions tgr ON tgr.tag_id = t.id #{outer_join ? "LEFT OUTER" : "INNER"} - JOIN category_restrictions cr ON t.id = cr.tag_id + JOIN category_restrictions cr ON t.id = cr.tag_id AND (tgr.tag_group_id = cr.category_tag_group_id OR cr.category_tag_group_id IS NULL) /*where*/ /*order_by*/ /*limit*/ @@ -572,7 +572,7 @@ module DiscourseTagging WHERE tg.one_per_topic SQL - if !one_tag_per_group_ids.empty? + if one_tag_per_group_ids.present? builder.where( "t.id NOT IN (SELECT DISTINCT tag_id FROM tag_group_restrictions WHERE tag_group_id IN (?)) OR id IN (:selected_tag_ids)", one_tag_per_group_ids, diff --git a/spec/lib/discourse_tagging_spec.rb b/spec/lib/discourse_tagging_spec.rb index 75f3779c825..305898620ac 100644 --- a/spec/lib/discourse_tagging_spec.rb +++ b/spec/lib/discourse_tagging_spec.rb @@ -1482,6 +1482,52 @@ RSpec.describe DiscourseTagging do end end + describe "Tag in multiple tag groups" do + fab!(:parent) { Fabricate(:tag) } + fab!(:child) { Fabricate(:tag) } + fab!(:no_show_tag) { Fabricate(:tag) } + + fab!(:no_show_tag_group) do + Fabricate(:tag_group, permissions: { "everyone" => 1 }, tag_names: [no_show_tag.name]) + end + + fab!(:child_tag_group) do + Fabricate( + :tag_group, + permissions: { + "everyone" => 1, + }, + tag_names: [child.name, no_show_tag.name], + parent_tag_id: parent.id, + ) + end + + fab!(:parent_tag_group) do + Fabricate(:tag_group, permissions: { "everyone" => 1 }, tag_names: [parent.name]) + end + + fab!(:category) do + Fabricate(:category, allowed_tag_groups: [parent_tag_group.name, child_tag_group.name]) + end + + # this test is to make sure that the parent tag is the only one returned when the child tag is also in a tag group + # allowed in the category + it "Will only return the parent tag" do + tags = + DiscourseTagging.filter_allowed_tags( + Guardian.new(user), + selected_tags: nil, + for_input: true, + category: category, + term: "", + ).map(&:name) + + expect(tags).to include(parent.name) + expect(tags).not_to include(child.name) + expect(tags).not_to include(no_show_tag.name) + end + end + describe "staff_tag_names" do fab!(:tag) { Fabricate(:tag) }