diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 5a8a8137b78..1108b618cc7 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -40,7 +40,7 @@ class TagsController < ::ApplicationController
if SiteSetting.tags_listed_by_group
ungrouped_tags = Tag.where("tags.id NOT IN (SELECT tag_id FROM tag_group_memberships)")
- ungrouped_tags = ungrouped_tags.where("tags.topic_count > 0") unless show_all_tags
+ ungrouped_tags = ungrouped_tags.used_tags_in_regular_topics(guardian) unless show_all_tags
grouped_tag_counts =
TagGroup
@@ -51,18 +51,14 @@ class TagsController < ::ApplicationController
{
id: tag_group.id,
name: tag_group.name,
- tags:
- self.class.tag_counts_json(
- tag_group.none_synonym_tags,
- show_pm_tags: guardian.can_tag_pms?,
- ),
+ tags: self.class.tag_counts_json(tag_group.none_synonym_tags, guardian),
}
end
- @tags = self.class.tag_counts_json(ungrouped_tags, show_pm_tags: guardian.can_tag_pms?)
+ @tags = self.class.tag_counts_json(ungrouped_tags, guardian)
@extras = { tag_groups: grouped_tag_counts }
else
- tags = show_all_tags ? Tag.all : Tag.where("tags.topic_count > 0")
+ tags = show_all_tags ? Tag.all : Tag.used_tags_in_regular_topics(guardian)
unrestricted_tags = DiscourseTagging.filter_visible(tags.where(target_tag_id: nil), guardian)
categories =
@@ -77,13 +73,14 @@ class TagsController < ::ApplicationController
category_tags =
self.class.tag_counts_json(
DiscourseTagging.filter_visible(c.tags.where(target_tag_id: nil), guardian),
+ guardian,
)
next if category_tags.empty?
{ id: c.id, tags: category_tags }
end
.compact
- @tags = self.class.tag_counts_json(unrestricted_tags, show_pm_tags: guardian.can_tag_pms?)
+ @tags = self.class.tag_counts_json(unrestricted_tags, guardian)
@extras = { categories: category_tag_counts }
end
@@ -264,7 +261,7 @@ class TagsController < ::ApplicationController
tags_with_counts, filter_result_context =
DiscourseTagging.filter_allowed_tags(guardian, **filter_params, with_context: true)
- tags = self.class.tag_counts_json(tags_with_counts, show_pm_tags: guardian.can_tag_pms?)
+ tags = self.class.tag_counts_json(tags_with_counts, guardian)
json_response = { results: tags }
@@ -388,18 +385,22 @@ class TagsController < ::ApplicationController
end
end
- def self.tag_counts_json(tags, show_pm_tags: true)
+ def self.tag_counts_json(tags, guardian)
+ show_pm_tags = guardian.can_tag_pms?
target_tags = Tag.where(id: tags.map(&:target_tag_id).compact.uniq).select(:id, :name)
+
tags
.map do |t|
- next if t.topic_count == 0 && t.pm_topic_count > 0 && !show_pm_tags
+ topic_count = t.public_send(Tag.topic_count_column(guardian))
+
+ next if topic_count == 0 && t.pm_topic_count > 0 && !show_pm_tags
{
id: t.name,
text: t.name,
name: t.name,
description: t.description,
- count: t.topic_count,
+ count: topic_count,
pm_count: show_pm_tags ? t.pm_topic_count : 0,
target_tag:
t.target_tag_id ? target_tags.find { |x| x.id == t.target_tag_id }&.name : nil,
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 64b932d02ed..71435ef046f 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -4,6 +4,10 @@ class Tag < ActiveRecord::Base
include Searchable
include HasDestroyedWebHook
+ self.ignored_columns = [
+ "topic_count", # TODO(tgxworld): Remove on 1 July 2023
+ ]
+
RESERVED_TAGS = [
"none",
"constructor", # prevents issues with javascript's constructor of objects
@@ -25,11 +29,14 @@ class Tag < ActiveRecord::Base
# tags that have never been used and don't belong to a tag group
scope :unused,
-> {
- where(topic_count: 0, pm_topic_count: 0).joins(
+ where(staff_topic_count: 0, pm_topic_count: 0).joins(
"LEFT JOIN tag_group_memberships tgm ON tags.id = tgm.tag_id",
).where("tgm.tag_id IS NULL")
}
+ scope :used_tags_in_regular_topics,
+ ->(guardian) { where("tags.#{Tag.topic_count_column(guardian)} > 0") }
+
scope :base_tags, -> { where(target_tag_id: nil) }
has_many :tag_users, dependent: :destroy # notification settings
@@ -62,7 +69,7 @@ class Tag < ActiveRecord::Base
def self.update_topic_counts
DB.exec <<~SQL
UPDATE tags t
- SET topic_count = x.topic_count
+ SET staff_topic_count = x.topic_count
FROM (
SELECT COUNT(topics.id) AS topic_count, tags.id AS tag_id
FROM tags
@@ -73,7 +80,31 @@ class Tag < ActiveRecord::Base
GROUP BY tags.id
) x
WHERE x.tag_id = t.id
- AND x.topic_count <> t.topic_count
+ AND x.topic_count <> t.staff_topic_count
+ SQL
+
+ DB.exec <<~SQL
+ UPDATE tags t
+ SET public_topic_count = x.topic_count
+ FROM (
+ WITH tags_with_public_topics AS (
+ SELECT
+ COUNT(topics.id) AS topic_count,
+ tags.id AS tag_id
+ FROM tags
+ INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
+ INNER JOIN topics ON topics.id = topic_tags.topic_id AND topics.deleted_at IS NULL AND topics.archetype != 'private_message'
+ INNER JOIN categories ON categories.id = topics.category_id AND NOT categories.read_restricted
+ GROUP BY tags.id
+ )
+ SELECT
+ COALESCE(tags_with_public_topics.topic_count, 0 ) AS topic_count,
+ tags.id AS tag_id
+ FROM tags
+ LEFT JOIN tags_with_public_topics ON tags_with_public_topics.tag_id = tags.id
+ ) x
+ WHERE x.tag_id = t.id
+ AND x.topic_count <> t.public_topic_count;
SQL
DB.exec <<~SQL
@@ -97,19 +128,18 @@ class Tag < ActiveRecord::Base
self.find_by("lower(name) = ?", name.downcase)
end
- def self.top_tags(limit_arg: nil, category: nil, guardian: nil)
+ def self.top_tags(limit_arg: nil, category: nil, guardian: Guardian.new)
# we add 1 to max_tags_in_filter_list to efficiently know we have more tags
# than the limit. Frontend is responsible to enforce limit.
limit = limit_arg || (SiteSetting.max_tags_in_filter_list + 1)
- scope_category_ids = (guardian || Guardian.new).allowed_category_ids
-
+ scope_category_ids = guardian.allowed_category_ids
scope_category_ids &= ([category.id] + category.subcategories.pluck(:id)) if category
return [] if scope_category_ids.empty?
filter_sql =
(
- if guardian&.is_staff?
+ if guardian.is_staff?
""
else
" AND tags.id IN (#{DiscourseTagging.visible_tags(guardian).select(:id).to_sql})"
@@ -130,6 +160,14 @@ class Tag < ActiveRecord::Base
tag_names_with_counts.map { |row| row.tag_name }
end
+ def self.topic_count_column(guardian)
+ if guardian&.is_staff? || SiteSetting.include_secure_categories_in_tag_counts
+ "staff_topic_count"
+ else
+ "public_topic_count"
+ end
+ end
+
def self.pm_tags(limit: 1000, guardian: nil, allowed_user: nil)
return [] if allowed_user.blank? || !(guardian || Guardian.new).can_tag_pms?
user_id = allowed_user.id
@@ -214,14 +252,15 @@ end
#
# Table name: tags
#
-# id :integer not null, primary key
-# name :string not null
-# topic_count :integer default(0), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# pm_topic_count :integer default(0), not null
-# target_tag_id :integer
-# description :string
+# id :integer not null, primary key
+# name :string not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# pm_topic_count :integer default(0), not null
+# target_tag_id :integer
+# description :string
+# public_topic_count :integer default(0), not null
+# staff_topic_count :integer default(0), not null
#
# Indexes
#
diff --git a/app/models/topic.rb b/app/models/topic.rb
index b15bbc519f6..10a0e7a5386 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -958,6 +958,7 @@ class Topic < ActiveRecord::Base
def changed_to_category(new_category)
return true if new_category.blank? || Category.exists?(topic_id: id)
+
if new_category.id == SiteSetting.uncategorized_category_id &&
!SiteSetting.allow_uncategorized_topics
return false
@@ -971,6 +972,15 @@ class Topic < ActiveRecord::Base
if old_category
Category.where(id: old_category.id).update_all("topic_count = topic_count - 1")
+
+ count =
+ if old_category.read_restricted && !new_category.read_restricted
+ 1
+ elsif !old_category.read_restricted && new_category.read_restricted
+ -1
+ end
+
+ Tag.update_counters(self.tags, { public_topic_count: count }) if count
end
# when a topic changes category we may have to start watching it
@@ -1781,12 +1791,15 @@ class Topic < ActiveRecord::Base
def convert_to_public_topic(user, category_id: nil)
public_topic = TopicConverter.new(self, user).convert_to_public_topic(category_id)
+ Tag.update_counters(public_topic.tags, { public_topic_count: 1 }) if !category.read_restricted
add_small_action(user, "public_topic") if public_topic
public_topic
end
def convert_to_private_message(user)
+ read_restricted = category.read_restricted
private_topic = TopicConverter.new(self, user).convert_to_private_message
+ Tag.update_counters(private_topic.tags, { public_topic_count: -1 }) if !read_restricted
add_small_action(user, "private_topic") if private_topic
private_topic
end
diff --git a/app/models/topic_tag.rb b/app/models/topic_tag.rb
index 67a8218d94a..b2ed69791a2 100644
--- a/app/models/topic_tag.rb
+++ b/app/models/topic_tag.rb
@@ -9,14 +9,18 @@ class TopicTag < ActiveRecord::Base
if topic.archetype == Archetype.private_message
tag.increment!(:pm_topic_count)
else
- tag.increment!(:topic_count)
+ counters_to_update = { staff_topic_count: 1 }
- if topic.category_id
- if stat = CategoryTagStat.find_by(tag_id: tag_id, category_id: topic.category_id)
- stat.increment!(:topic_count)
- else
- CategoryTagStat.create(tag_id: tag_id, category_id: topic.category_id, topic_count: 1)
- end
+ if Category.exists?(id: topic.category_id, read_restricted: false)
+ counters_to_update[:public_topic_count] = 1
+ end
+
+ Tag.update_counters(tag.id, counters_to_update)
+
+ if stat = CategoryTagStat.find_by(tag_id: tag_id, category_id: topic.category_id)
+ stat.increment!(:topic_count)
+ else
+ CategoryTagStat.create!(tag_id: tag_id, category_id: topic.category_id, topic_count: 1)
end
end
end
@@ -27,12 +31,17 @@ class TopicTag < ActiveRecord::Base
if topic.archetype == Archetype.private_message
tag.decrement!(:pm_topic_count)
else
- if topic.category_id &&
- stat = CategoryTagStat.find_by(tag_id: tag_id, category: topic.category_id)
- stat.topic_count == 1 ? stat.destroy : stat.decrement!(:topic_count)
+ if stat = CategoryTagStat.find_by(tag_id: tag_id, category: topic.category_id)
+ stat.topic_count == 1 ? stat.destroy! : stat.decrement!(:topic_count)
end
- tag.decrement!(:topic_count)
+ counters_to_update = { staff_topic_count: -1 }
+
+ if Category.exists?(id: topic.category_id, read_restricted: false)
+ counters_to_update[:public_topic_count] = -1
+ end
+
+ Tag.update_counters(tag.id, counters_to_update)
end
end
end
diff --git a/app/serializers/concerns/topic_tags_mixin.rb b/app/serializers/concerns/topic_tags_mixin.rb
index 2704ba33611..0c001d46334 100644
--- a/app/serializers/concerns/topic_tags_mixin.rb
+++ b/app/serializers/concerns/topic_tags_mixin.rb
@@ -32,7 +32,8 @@ module TopicTagsMixin
if SiteSetting.tags_sort_alphabetically
topic.tags.sort_by(&:name)
else
- topic.tags.sort_by(&:topic_count).reverse
+ topic_count_column = Tag.topic_count_column(scope)
+ topic.tags.sort_by { |tag| tag.public_send(topic_count_column) }.reverse
end
)
tags = tags.reject { |tag| scope.hidden_tag_names.include?(tag[:name]) } if !scope.is_staff?
diff --git a/app/serializers/concerns/user_sidebar_mixin.rb b/app/serializers/concerns/user_sidebar_mixin.rb
index f70b97bec28..5f8c5add0a1 100644
--- a/app/serializers/concerns/user_sidebar_mixin.rb
+++ b/app/serializers/concerns/user_sidebar_mixin.rb
@@ -2,9 +2,11 @@
module UserSidebarMixin
def sidebar_tags
+ topic_count_column = Tag.topic_count_column(scope)
+
object
.visible_sidebar_tags(scope)
- .pluck(:name, :topic_count, :pm_topic_count)
+ .pluck(:name, topic_count_column, :pm_topic_count)
.reduce([]) do |tags, sidebar_tag|
tags.push(name: sidebar_tag[0], pm_only: sidebar_tag[1] == 0 && sidebar_tag[2] > 0)
end
diff --git a/app/serializers/detailed_tag_serializer.rb b/app/serializers/detailed_tag_serializer.rb
index 83570c3d5e0..7fd7a3943b0 100644
--- a/app/serializers/detailed_tag_serializer.rb
+++ b/app/serializers/detailed_tag_serializer.rb
@@ -6,7 +6,7 @@ class DetailedTagSerializer < TagSerializer
has_many :categories, serializer: BasicCategorySerializer
def synonyms
- TagsController.tag_counts_json(object.synonyms)
+ TagsController.tag_counts_json(object.synonyms, scope)
end
def categories
diff --git a/app/serializers/tag_serializer.rb b/app/serializers/tag_serializer.rb
index 6fa46a80bdf..81e55156965 100644
--- a/app/serializers/tag_serializer.rb
+++ b/app/serializers/tag_serializer.rb
@@ -3,6 +3,10 @@
class TagSerializer < ApplicationSerializer
attributes :id, :name, :topic_count, :staff, :description
+ def topic_count
+ object.public_send(Tag.topic_count_column(scope))
+ end
+
def staff
DiscourseTagging.staff_tag_names.include?(name)
end
diff --git a/app/services/tag_hashtag_data_source.rb b/app/services/tag_hashtag_data_source.rb
index 11b089c84f5..b186ca12c42 100644
--- a/app/services/tag_hashtag_data_source.rb
+++ b/app/services/tag_hashtag_data_source.rb
@@ -12,26 +12,30 @@ class TagHashtagDataSource
"tag"
end
- def self.tag_to_hashtag_item(tag)
- tag = Tag.new(tag.slice(:id, :name, :description).merge(topic_count: tag[:count])) if tag.is_a?(
- Hash,
- )
+ def self.tag_to_hashtag_item(tag, guardian)
+ topic_count_column = Tag.topic_count_column(guardian)
+
+ tag =
+ Tag.new(
+ tag.slice(:id, :name, :description).merge(topic_count_column => tag[:count]),
+ ) if tag.is_a?(Hash)
HashtagAutocompleteService::HashtagItem.new.tap do |item|
item.text = tag.name
- item.secondary_text = "x#{tag.topic_count}"
+ item.secondary_text = "x#{tag.public_send(topic_count_column)}"
item.description = tag.description
item.slug = tag.name
item.relative_url = tag.url
item.icon = icon
end
end
+ private_class_method :tag_to_hashtag_item
def self.lookup(guardian, slugs)
return [] if !SiteSetting.tagging_enabled
DiscourseTagging
.filter_visible(Tag.where_name(slugs), guardian)
- .map { |tag| tag_to_hashtag_item(tag) }
+ .map { |tag| tag_to_hashtag_item(tag, guardian) }
end
def self.search(
@@ -60,9 +64,9 @@ class TagHashtagDataSource
)
TagsController
- .tag_counts_json(tags_with_counts)
+ .tag_counts_json(tags_with_counts, guardian)
.take(limit)
- .map { |tag| tag_to_hashtag_item(tag) }
+ .map { |tag| tag_to_hashtag_item(tag, guardian) }
end
def self.search_sort(search_results, _)
@@ -82,8 +86,8 @@ class TagHashtagDataSource
)
TagsController
- .tag_counts_json(tags_with_counts)
+ .tag_counts_json(tags_with_counts, guardian)
.take(limit)
- .map { |tag| tag_to_hashtag_item(tag) }
+ .map { |tag| tag_to_hashtag_item(tag, guardian) }
end
end
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 88121e6d877..6fa88945fa8 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1651,6 +1651,7 @@ en:
content_security_policy_frame_ancestors: "Restrict who can embed this site in iframes via CSP. Control allowed hosts on Embedding"
content_security_policy_script_src: "Additional allowlisted script sources. The current host and CDN are included by default. See Mitigate XSS Attacks with Content Security Policy."
invalidate_inactive_admin_email_after_days: "Admin accounts that have not visited the site in this number of days will need to re-validate their email address before logging in. Set to 0 to disable."
+ include_secure_categories_in_tag_counts: "When enabled, count of topics for a tag will include topics that are in read restricted categories for all users. When disabled, normal users are only shown a count of topics for a tag where all the topics are in public categories."
top_menu: "Determine which items appear in the homepage navigation, and in what order. Example latest|new|unread|categories|top|read|posted|bookmarks"
post_menu: "Determine which items appear on the post menu, and in what order. Example like|edit|flag|delete|share|bookmark|reply"
post_menu_hidden_items: "The menu items to hide by default in the post menu unless an expansion ellipsis is clicked on."
diff --git a/config/site_settings.yml b/config/site_settings.yml
index e565dc1725d..5967fe135b5 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -1798,6 +1798,8 @@ security:
suppress_secured_categories_from_admin:
default: false
hidden: true
+ include_secure_categories_in_tag_counts:
+ default: false
onebox:
post_onebox_maxlength:
diff --git a/db/migrate/20230118020114_add_public_topic_count_to_tags.rb b/db/migrate/20230118020114_add_public_topic_count_to_tags.rb
new file mode 100644
index 00000000000..73b9064635a
--- /dev/null
+++ b/db/migrate/20230118020114_add_public_topic_count_to_tags.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class AddPublicTopicCountToTags < ActiveRecord::Migration[7.0]
+ def up
+ add_column :tags, :public_topic_count, :integer, default: 0, null: false
+
+ execute <<~SQL
+ UPDATE tags t
+ SET public_topic_count = x.topic_count
+ FROM (
+ SELECT
+ COUNT(topics.id) AS topic_count,
+ tags.id AS tag_id
+ FROM tags
+ INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
+ INNER JOIN topics ON topics.id = topic_tags.topic_id AND topics.deleted_at IS NULL AND topics.archetype != 'private_message'
+ INNER JOIN categories ON categories.id = topics.category_id AND NOT categories.read_restricted
+ GROUP BY tags.id
+ ) x
+ WHERE x.tag_id = t.id
+ AND x.topic_count <> t.public_topic_count;
+ SQL
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/migrate/20230119000943_add_staff_topic_count_to_tags.rb b/db/migrate/20230119000943_add_staff_topic_count_to_tags.rb
new file mode 100644
index 00000000000..0154c126246
--- /dev/null
+++ b/db/migrate/20230119000943_add_staff_topic_count_to_tags.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddStaffTopicCountToTags < ActiveRecord::Migration[7.0]
+ def up
+ add_column :tags, :staff_topic_count, :integer, default: 0, null: false
+
+ execute <<~SQL
+ UPDATE tags t
+ SET staff_topic_count = x.topic_count
+ FROM (
+ SELECT COUNT(topics.id) AS topic_count, tags.id AS tag_id
+ FROM tags
+ LEFT JOIN topic_tags ON tags.id = topic_tags.tag_id
+ LEFT JOIN topics ON topics.id = topic_tags.topic_id
+ AND topics.deleted_at IS NULL
+ AND topics.archetype != 'private_message'
+ GROUP BY tags.id
+ ) x
+ WHERE x.tag_id = t.id
+ AND x.topic_count <> t.staff_topic_count
+ SQL
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/post_migrate/20230119024157_remove_topic_count_from_tags.rb b/db/post_migrate/20230119024157_remove_topic_count_from_tags.rb
new file mode 100644
index 00000000000..f51e3a1bcd5
--- /dev/null
+++ b/db/post_migrate/20230119024157_remove_topic_count_from_tags.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require "migration/column_dropper"
+
+class RemoveTopicCountFromTags < ActiveRecord::Migration[7.0]
+ DROPPED_COLUMNS ||= { tags: %i[topic_count] }
+
+ def up
+ DROPPED_COLUMNS.each { |table, columns| Migration::ColumnDropper.execute_drop(table, columns) }
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/lib/discourse_tagging.rb b/lib/discourse_tagging.rb
index 8a8c2d7f878..0fd1583be1a 100644
--- a/lib/discourse_tagging.rb
+++ b/lib/discourse_tagging.rb
@@ -323,17 +323,19 @@ module DiscourseTagging
outer_join = category.nil? || category.allow_global_tags || !category_has_restricted_tags
+ topic_count_column = Tag.topic_count_column(guardian)
+
distinct_clause =
if opts[:order_popularity]
- "DISTINCT ON (topic_count, name)"
+ "DISTINCT ON (#{topic_count_column}, name)"
elsif opts[:order_search_results] && opts[:term].present?
- "DISTINCT ON (lower(name) = lower(:cleaned_term), topic_count, name)"
+ "DISTINCT ON (lower(name) = lower(:cleaned_term), #{topic_count_column}, name)"
else
""
end
sql << <<~SQL
- SELECT #{distinct_clause} t.id, t.name, t.topic_count, t.pm_topic_count, t.description,
+ SELECT #{distinct_clause} t.id, t.name, t.#{topic_count_column}, t.pm_topic_count, t.description,
tgr.tgm_id as tgm_id, tgr.tag_group_id as tag_group_id, tgr.parent_tag_id as parent_tag_id,
tgr.one_per_topic as one_per_topic, t.target_tag_id
FROM tags t
@@ -479,9 +481,9 @@ module DiscourseTagging
end
if opts[:order_popularity]
- builder.order_by("topic_count DESC, name")
+ builder.order_by("#{topic_count_column} DESC, name")
elsif opts[:order_search_results] && !term.blank?
- builder.order_by("lower(name) = lower(:cleaned_term) DESC, topic_count DESC, name")
+ builder.order_by("lower(name) = lower(:cleaned_term) DESC, #{topic_count_column} DESC, name")
end
result = builder.query(builder_params).uniq { |t| t.id }
diff --git a/lib/topic_view.rb b/lib/topic_view.rb
index f6b9c19259e..576b6d3c5c3 100644
--- a/lib/topic_view.rb
+++ b/lib/topic_view.rb
@@ -245,7 +245,8 @@ class TopicView
@topic.category
title += " - #{@topic.category.name}"
elsif SiteSetting.tagging_enabled && @topic.tags.exists?
- title += " - #{@topic.tags.order("tags.topic_count DESC").first.name}"
+ title +=
+ " - #{@topic.tags.order("tags.#{Tag.topic_count_column(@guardian)} DESC").first.name}"
end
end
title
diff --git a/spec/integration/tag_counts_spec.rb b/spec/integration/tag_counts_spec.rb
new file mode 100644
index 00000000000..82ec44d7b30
--- /dev/null
+++ b/spec/integration/tag_counts_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+RSpec.describe "Updating tag counts" do
+ fab!(:tag1) { Fabricate(:tag) }
+ fab!(:tag2) { Fabricate(:tag) }
+ fab!(:group) { Fabricate(:group) }
+ fab!(:public_category) { Fabricate(:category) }
+ fab!(:public_category2) { Fabricate(:category) }
+ fab!(:private_category) { Fabricate(:private_category, group: group) }
+ fab!(:private_category2) { Fabricate(:private_category, group: group) }
+
+ fab!(:topic_in_public_category) do
+ Fabricate(:topic, category: public_category, tags: [tag1, tag2]).tap do |topic|
+ Fabricate(:post, topic: topic)
+ end
+ end
+
+ fab!(:topic_in_private_category) do
+ Fabricate(:topic, category: private_category, tags: [tag1, tag2]).tap do |topic|
+ Fabricate(:post, topic: topic)
+ end
+ end
+
+ fab!(:private_message) do
+ topic = Fabricate(:private_message_post).topic
+ topic.update!(tags: [tag1, tag2])
+ topic
+ end
+
+ before do
+ expect(tag1.public_topic_count).to eq(1)
+ expect(tag1.staff_topic_count).to eq(2)
+ expect(tag1.pm_topic_count).to eq(1)
+ expect(tag2.reload.public_topic_count).to eq(1)
+ expect(tag2.staff_topic_count).to eq(2)
+ expect(tag2.pm_topic_count).to eq(1)
+ end
+
+ it "should decrease Tag#public_topic_count for all tags when topic's category is changed from a public category to a read restricted category" do
+ expect { topic_in_public_category.change_category_to_id(private_category.id) }.to change {
+ tag1.reload.public_topic_count
+ }.by(-1).and change { tag2.reload.public_topic_count }.by(-1)
+ end
+
+ it "should increase Tag#public_topic_count for all tags when topic's category is changed from a read restricted category to a public category" do
+ expect { topic_in_private_category.change_category_to_id(public_category.id) }.to change {
+ tag1.reload.public_topic_count
+ }.by(1).and change { tag2.reload.public_topic_count }.by(1)
+ end
+
+ it "should not change Tag#public_topic_count for all tags when topic's category is changed from a public category to another public category" do
+ expect do
+ topic_in_public_category.change_category_to_id(public_category2.id)
+ end.to not_change { tag1.reload.public_topic_count }.and not_change {
+ tag2.reload.public_topic_count
+ }
+ end
+
+ it "should not change Tag#public_topic_count for all tags when topic's category is changed from a read restricted category to another read restricted category" do
+ expect do
+ topic_in_private_category.change_category_to_id(private_category2.id)
+ end.to not_change { tag1.reload.public_topic_count }.and not_change {
+ tag2.reload.public_topic_count
+ }
+ end
+
+ it "increases Tag#public_topic_count for all tags when topic is converted from private message to a regular topic in a public category" do
+ expect do
+ private_message.convert_to_public_topic(
+ Discourse.system_user,
+ category_id: public_category.id,
+ )
+ end.to change { tag1.reload.public_topic_count }.by(1).and change {
+ tag2.reload.public_topic_count
+ }.by(1)
+ end
+
+ it "should not change Tag#public_topic_count for all tags when topic is converted from private message to a regular topic in a read restricted category" do
+ expect do
+ private_message.convert_to_public_topic(
+ Discourse.system_user,
+ category_id: private_category.id,
+ )
+ end.to not_change { tag1.reload.public_topic_count }.and not_change {
+ tag2.reload.public_topic_count
+ }
+ end
+
+ it "should decrease Tag#public_topic_count for all tags when regular topic in public category is converted to a private message" do
+ expect do
+ topic_in_public_category.convert_to_private_message(Discourse.system_user)
+ end.to change { tag1.reload.public_topic_count }.by(-1).and change {
+ tag2.reload.public_topic_count
+ }.by(-1)
+ end
+
+ it "should not change Tag#public_topic_count for all tags when regular topic in read restricted category is converted to a private message" do
+ expect do
+ topic_in_private_category.convert_to_private_message(Discourse.system_user)
+ end.to not_change { tag1.reload.public_topic_count }.and not_change {
+ tag2.reload.public_topic_count
+ }
+ end
+end
diff --git a/spec/lib/discourse_tagging_spec.rb b/spec/lib/discourse_tagging_spec.rb
index 1188243c57e..02782eefd5d 100644
--- a/spec/lib/discourse_tagging_spec.rb
+++ b/spec/lib/discourse_tagging_spec.rb
@@ -641,9 +641,11 @@ RSpec.describe DiscourseTagging do
it "user does not get an error when editing their topic with a hidden tag" do
PostRevisor.new(post).revise!(admin, raw: post.raw, tags: [hidden_tag.name])
+
expect(
PostRevisor.new(post).revise!(topic.user, raw: post.raw + " edit", tags: []),
).to be_truthy
+
expect(topic.reload.tags).to eq([hidden_tag])
end
end
@@ -967,8 +969,16 @@ RSpec.describe DiscourseTagging do
topic = Fabricate(:topic, tags: [tag2])
expect(DiscourseTagging.add_or_create_synonyms_by_name(tag1, [tag2.name])).to eq(true)
expect_same_tag_names(topic.reload.tags, [tag1])
- expect(tag1.reload.topic_count).to eq(1)
- expect(tag2.reload.topic_count).to eq(0)
+
+ tag1.reload
+
+ expect(tag1.public_topic_count).to eq(1)
+ expect(tag1.staff_topic_count).to eq(1)
+
+ tag2.reload
+
+ expect(tag2.public_topic_count).to eq(0)
+ expect(tag2.staff_topic_count).to eq(0)
end
end
end
diff --git a/spec/lib/topic_view_spec.rb b/spec/lib/topic_view_spec.rb
index 7dc2ff115fc..50328464889 100644
--- a/spec/lib/topic_view_spec.rb
+++ b/spec/lib/topic_view_spec.rb
@@ -750,8 +750,8 @@ RSpec.describe TopicView do
end
describe "page_title" do
- fab!(:tag1) { Fabricate(:tag) }
- fab!(:tag2) { Fabricate(:tag, topic_count: 2) }
+ fab!(:tag1) { Fabricate(:tag, staff_topic_count: 0, public_topic_count: 0) }
+ fab!(:tag2) { Fabricate(:tag, staff_topic_count: 2, public_topic_count: 2) }
fab!(:op_post) { Fabricate(:post, topic: topic) }
fab!(:post1) { Fabricate(:post, topic: topic) }
fab!(:whisper) { Fabricate(:post, topic: topic, post_type: Post.types[:whisper]) }
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index 7aff07ab795..402c6c73349 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -202,29 +202,101 @@ RSpec.describe Tag do
end
end
- describe "topic counts" do
+ describe ".ensure_consistency!" do
it "should exclude private message topics" do
topic
Fabricate(:private_message_topic, tags: [tag])
Tag.ensure_consistency!
tag.reload
- expect(tag.topic_count).to eq(1)
+ expect(tag.staff_topic_count).to eq(1)
+ expect(tag.public_topic_count).to eq(1)
+ end
+
+ it "should update Tag#topic_count and Tag#public_topic_count correctly" do
+ tag = Fabricate(:tag, name: "tag1")
+ tag2 = Fabricate(:tag, name: "tag2")
+ tag3 = Fabricate(:tag, name: "tag3")
+ group = Fabricate(:group)
+ category = Fabricate(:category)
+ private_category = Fabricate(:private_category, group: group)
+ private_category2 = Fabricate(:private_category, group: group)
+
+ _topic_with_tag = Fabricate(:topic, category: category, tags: [tag])
+
+ _topic_with_tag_in_private_category =
+ Fabricate(:topic, category: private_category, tags: [tag])
+
+ _topic_with_tag2_in_private_category2 =
+ Fabricate(:topic, category: private_category2, tags: [tag2])
+
+ tag.update!(staff_topic_count: 123, public_topic_count: 456)
+ tag2.update!(staff_topic_count: 123, public_topic_count: 456)
+ tag3.update!(staff_topic_count: 123, public_topic_count: 456)
+
+ Tag.ensure_consistency!
+
+ tag.reload
+ tag2.reload
+ tag3.reload
+
+ expect(tag.staff_topic_count).to eq(2)
+ expect(tag.public_topic_count).to eq(1)
+ expect(tag2.staff_topic_count).to eq(1)
+ expect(tag2.public_topic_count).to eq(0)
+ expect(tag3.staff_topic_count).to eq(0)
+ expect(tag3.public_topic_count).to eq(0)
end
end
describe "unused tags scope" do
let!(:tags) do
[
- Fabricate(:tag, name: "used_publically", topic_count: 2, pm_topic_count: 0),
- Fabricate(:tag, name: "used_privately", topic_count: 0, pm_topic_count: 3),
- Fabricate(:tag, name: "used_everywhere", topic_count: 0, pm_topic_count: 3),
- Fabricate(:tag, name: "unused1", topic_count: 0, pm_topic_count: 0),
- Fabricate(:tag, name: "unused2", topic_count: 0, pm_topic_count: 0),
+ Fabricate(
+ :tag,
+ name: "used_publically",
+ staff_topic_count: 2,
+ public_topic_count: 2,
+ pm_topic_count: 0,
+ ),
+ Fabricate(
+ :tag,
+ name: "used_privately",
+ staff_topic_count: 0,
+ public_topic_count: 0,
+ pm_topic_count: 3,
+ ),
+ Fabricate(
+ :tag,
+ name: "used_everywhere",
+ staff_topic_count: 0,
+ public_topic_count: 0,
+ pm_topic_count: 3,
+ ),
+ Fabricate(
+ :tag,
+ name: "unused1",
+ staff_topic_count: 0,
+ public_topic_count: 0,
+ pm_topic_count: 0,
+ ),
+ Fabricate(
+ :tag,
+ name: "unused2",
+ staff_topic_count: 0,
+ public_topic_count: 0,
+ pm_topic_count: 0,
+ ),
]
end
let(:tag_in_group) do
- Fabricate(:tag, name: "unused_in_group", topic_count: 0, pm_topic_count: 0)
+ Fabricate(
+ :tag,
+ name: "unused_in_group",
+ public_topic_count: 0,
+ staff_topic_count: 0,
+ pm_topic_count: 0,
+ )
end
let!(:tag_group) { Fabricate(:tag_group, tag_names: [tag_in_group.name]) }
@@ -292,4 +364,22 @@ RSpec.describe Tag do
expect(category.reload.tags).to include(tag2)
end
end
+
+ describe ".topic_count_column" do
+ fab!(:admin) { Fabricate(:admin) }
+
+ it "returns 'staff_topic_count' when user is staff" do
+ expect(Tag.topic_count_column(Guardian.new(admin))).to eq("staff_topic_count")
+ end
+
+ it "returns 'public_topic_count' when user is not staff" do
+ expect(Tag.topic_count_column(Guardian.new(user))).to eq("public_topic_count")
+ end
+
+ it "returns 'staff_topic_count' when user is not staff but `include_secure_categories_in_tag_counts` site setting is enabled" do
+ SiteSetting.include_secure_categories_in_tag_counts = true
+
+ expect(Tag.topic_count_column(Guardian.new(user))).to eq("staff_topic_count")
+ end
+ end
end
diff --git a/spec/models/topic_tag_spec.rb b/spec/models/topic_tag_spec.rb
index 33779f1e34e..b4a8e231cef 100644
--- a/spec/models/topic_tag_spec.rb
+++ b/spec/models/topic_tag_spec.rb
@@ -1,33 +1,56 @@
# frozen_string_literal: true
RSpec.describe TopicTag do
+ fab!(:group) { Fabricate(:group) }
+ fab!(:private_category) { Fabricate(:private_category, group: group) }
fab!(:topic) { Fabricate(:topic) }
+ fab!(:topic_in_private_category) { Fabricate(:topic, category: private_category) }
fab!(:tag) { Fabricate(:tag) }
let(:topic_tag) { Fabricate(:topic_tag, topic: topic, tag: tag) }
describe "#after_create" do
- it "tag topic_count should be increased" do
- expect { topic_tag }.to change(tag, :topic_count).by(1)
+ it "should increase Tag#staff_topic_count and Tag#public_topic_count for a regular topic in a public category" do
+ expect { topic_tag }.to change { tag.reload.staff_topic_count }.by(1).and change {
+ tag.reload.public_topic_count
+ }.by(1)
end
- it "tag topic_count should not be increased" do
+ it "should only increase Tag#staff_topic_count for a regular topic in a read restricted category" do
+ expect { Fabricate(:topic_tag, topic: topic_in_private_category, tag: tag) }.to change {
+ tag.reload.staff_topic_count
+ }.by(1)
+
+ expect(tag.reload.public_topic_count).to eq(0)
+ end
+
+ it "should increase Tag#pm_topic_count for a private message topic" do
topic.archetype = Archetype.private_message
- expect { topic_tag }.not_to change(tag, :topic_count)
+ expect { topic_tag }.to change { tag.reload.pm_topic_count }.by(1)
end
end
describe "#after_destroy" do
- it "tag topic_count should be decreased" do
+ it "should decrease Tag#staff_topic_count and Tag#public_topic_count for a regular topic in a public category" do
topic_tag
- expect { topic_tag.destroy }.to change(tag, :topic_count).by(-1)
+
+ expect { topic_tag.destroy! }.to change { tag.reload.staff_topic_count }.by(-1).and change {
+ tag.reload.public_topic_count
+ }.by(-1)
end
- it "tag topic_count should not be decreased" do
+ it "should only decrease Topic#topic_count for a regular topic in a read restricted category" do
+ topic_tag = Fabricate(:topic_tag, topic: topic_in_private_category, tag: tag)
+
+ expect { topic_tag.destroy! }.to change { tag.reload.staff_topic_count }.by(-1)
+ expect(tag.reload.public_topic_count).to eq(0)
+ end
+
+ it "should decrease Tag#pm_topic_count for a private message topic" do
topic.archetype = Archetype.private_message
topic_tag
- expect { topic_tag.destroy }.not_to change(tag, :topic_count)
+ expect { topic_tag.destroy! }.to change { tag.reload.pm_topic_count }.by(-1)
end
end
end
diff --git a/spec/requests/tags_controller_spec.rb b/spec/requests/tags_controller_spec.rb
index 8664605a4c3..834589618be 100644
--- a/spec/requests/tags_controller_spec.rb
+++ b/spec/requests/tags_controller_spec.rb
@@ -12,18 +12,43 @@ RSpec.describe TagsController do
describe "#index" do
fab!(:test_tag) { Fabricate(:tag, name: "test") }
- fab!(:topic_tag) { Fabricate(:tag, name: "topic-test", topic_count: 1) }
+ fab!(:topic_tag) do
+ Fabricate(:tag, name: "topic-test", public_topic_count: 1, staff_topic_count: 1)
+ end
fab!(:synonym) { Fabricate(:tag, name: "synonym", target_tag: topic_tag) }
- shared_examples "successfully retrieve tags with topic_count > 0" do
- it "should return the right response" do
+ shared_examples "retrieves the right tags" do
+ it "retrieves all tags as a staff user" do
+ sign_in(admin)
+
+ get "/tags.json"
+
+ expect(response.status).to eq(200)
+
+ tags = response.parsed_body["tags"]
+
+ expect(tags[0]["name"]).to eq(test_tag.name)
+ expect(tags[0]["count"]).to eq(0)
+ expect(tags[0]["pm_count"]).to eq(0)
+
+ expect(tags[1]["name"]).to eq(topic_tag.name)
+ expect(tags[1]["count"]).to eq(1)
+ expect(tags[1]["pm_count"]).to eq(0)
+ end
+
+ it "only retrieve tags that have been used in public topics for non-staff user" do
+ sign_in(user)
+
get "/tags.json"
expect(response.status).to eq(200)
tags = response.parsed_body["tags"]
expect(tags.length).to eq(1)
- expect(tags[0]["text"]).to eq("topic-test")
+
+ expect(tags[0]["name"]).to eq(topic_tag.name)
+ expect(tags[0]["count"]).to eq(1)
+ expect(tags[0]["pm_count"]).to eq(0)
end
end
@@ -76,7 +101,7 @@ RSpec.describe TagsController do
context "with tags_listed_by_group enabled" do
before { SiteSetting.tags_listed_by_group = true }
- include_examples "successfully retrieve tags with topic_count > 0"
+ include_examples "retrieves the right tags"
it "works for tags in groups" do
tag_group = Fabricate(:tag_group, tags: [test_tag, topic_tag, synonym])
@@ -136,20 +161,7 @@ RSpec.describe TagsController do
context "with tags_listed_by_group disabled" do
before { SiteSetting.tags_listed_by_group = false }
- include_examples "successfully retrieve tags with topic_count > 0"
- end
-
- context "when user can admin tags" do
- it "successfully retrieve all tags" do
- sign_in(admin)
-
- get "/tags.json"
-
- expect(response.status).to eq(200)
-
- tags = response.parsed_body["tags"]
- expect(tags.length).to eq(2)
- end
+ include_examples "retrieves the right tags"
end
context "with hidden tags" do
@@ -763,10 +775,10 @@ RSpec.describe TagsController do
expect(response.parsed_body["results"].map { |j| j["id"] }.sort).to eq(%w[stuff stumped])
end
- it "returns tags ordered by topic_count, and prioritises exact matches" do
- Fabricate(:tag, name: "tag1", topic_count: 10)
- Fabricate(:tag, name: "tag2", topic_count: 100)
- Fabricate(:tag, name: "tag", topic_count: 1)
+ it "returns tags ordered by public_topic_count, and prioritises exact matches" do
+ Fabricate(:tag, name: "tag1", public_topic_count: 10, staff_topic_count: 10)
+ Fabricate(:tag, name: "tag2", public_topic_count: 100, staff_topic_count: 100)
+ Fabricate(:tag, name: "tag", public_topic_count: 1, staff_topic_count: 1)
get "/tags/filter/search.json", params: { q: "tag", limit: 2 }
expect(response.status).to eq(200)
@@ -976,11 +988,41 @@ RSpec.describe TagsController do
context "with some tags" do
let!(:tags) do
[
- Fabricate(:tag, name: "used_publically", topic_count: 2, pm_topic_count: 0),
- Fabricate(:tag, name: "used_privately", topic_count: 0, pm_topic_count: 3),
- Fabricate(:tag, name: "used_everywhere", topic_count: 0, pm_topic_count: 3),
- Fabricate(:tag, name: "unused1", topic_count: 0, pm_topic_count: 0),
- Fabricate(:tag, name: "unused2", topic_count: 0, pm_topic_count: 0),
+ Fabricate(
+ :tag,
+ name: "used_publically",
+ public_topic_count: 2,
+ staff_topic_count: 2,
+ pm_topic_count: 0,
+ ),
+ Fabricate(
+ :tag,
+ name: "used_privately",
+ public_topic_count: 0,
+ staff_topic_count: 0,
+ pm_topic_count: 3,
+ ),
+ Fabricate(
+ :tag,
+ name: "used_everywhere",
+ public_topic_count: 0,
+ staff_topic_count: 0,
+ pm_topic_count: 3,
+ ),
+ Fabricate(
+ :tag,
+ name: "unused1",
+ public_topic_count: 0,
+ staff_topic_count: 0,
+ pm_topic_count: 0,
+ ),
+ Fabricate(
+ :tag,
+ name: "unused2",
+ public_topic_count: 0,
+ staff_topic_count: 0,
+ pm_topic_count: 0,
+ ),
]
end
diff --git a/spec/serializers/tag_serializer_spec.rb b/spec/serializers/tag_serializer_spec.rb
new file mode 100644
index 00000000000..c9eab114fc7
--- /dev/null
+++ b/spec/serializers/tag_serializer_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+RSpec.describe TagSerializer do
+ fab!(:user) { Fabricate(:user) }
+ fab!(:admin) { Fabricate(:admin) }
+ fab!(:tag) { Fabricate(:tag) }
+ fab!(:group) { Fabricate(:group) }
+ fab!(:private_category) { Fabricate(:private_category, group: group) }
+ fab!(:topic_in_public_category) { Fabricate(:topic, tags: [tag]) }
+ fab!(:topic_in_private_category) { Fabricate(:topic, category: private_category, tags: [tag]) }
+
+ describe "#topic_count" do
+ it "should return the value of `Tag#public_topic_count` for a non-staff user" do
+ serialized = described_class.new(tag, scope: Guardian.new(user), root: false).as_json
+
+ expect(serialized[:topic_count]).to eq(1)
+ end
+
+ it "should return the vavlue of `Tag#topic_count` for a staff user" do
+ serialized = described_class.new(tag, scope: Guardian.new(admin), root: false).as_json
+
+ expect(serialized[:topic_count]).to eq(2)
+ end
+ end
+end
diff --git a/spec/serializers/topic_view_serializer_spec.rb b/spec/serializers/topic_view_serializer_spec.rb
index 1d064811c80..015ef3d1f3c 100644
--- a/spec/serializers/topic_view_serializer_spec.rb
+++ b/spec/serializers/topic_view_serializer_spec.rb
@@ -279,9 +279,33 @@ RSpec.describe TopicViewSerializer do
end
describe "tags order" do
- fab!(:tag1) { Fabricate(:tag, name: "ctag", description: "c description", topic_count: 5) }
- fab!(:tag2) { Fabricate(:tag, name: "btag", description: "b description", topic_count: 9) }
- fab!(:tag3) { Fabricate(:tag, name: "atag", description: "a description", topic_count: 3) }
+ fab!(:tag1) do
+ Fabricate(
+ :tag,
+ name: "ctag",
+ description: "c description",
+ staff_topic_count: 5,
+ public_topic_count: 5,
+ )
+ end
+ fab!(:tag2) do
+ Fabricate(
+ :tag,
+ name: "btag",
+ description: "b description",
+ staff_topic_count: 9,
+ public_topic_count: 9,
+ )
+ end
+ fab!(:tag3) do
+ Fabricate(
+ :tag,
+ name: "atag",
+ description: "a description",
+ staff_topic_count: 3,
+ public_topic_count: 3,
+ )
+ end
before do
topic.tags << tag1
diff --git a/spec/services/hashtag_autocomplete_service_spec.rb b/spec/services/hashtag_autocomplete_service_spec.rb
index f37eb5810c9..986124548dd 100644
--- a/spec/services/hashtag_autocomplete_service_spec.rb
+++ b/spec/services/hashtag_autocomplete_service_spec.rb
@@ -3,7 +3,9 @@
RSpec.describe HashtagAutocompleteService do
fab!(:user) { Fabricate(:user) }
fab!(:category1) { Fabricate(:category, name: "The Book Club", slug: "the-book-club") }
- fab!(:tag1) { Fabricate(:tag, name: "great-books", topic_count: 22) }
+ fab!(:tag1) do
+ Fabricate(:tag, name: "great-books", staff_topic_count: 22, public_topic_count: 22)
+ end
fab!(:topic1) { Fabricate(:topic) }
let(:guardian) { Guardian.new(user) }
@@ -68,7 +70,7 @@ RSpec.describe HashtagAutocompleteService do
end
it "includes the tag count" do
- tag1.update!(topic_count: 78)
+ tag1.update!(staff_topic_count: 78, public_topic_count: 78)
expect(subject.search("book", %w[tag category]).map(&:text)).to eq(
["great-books", "The Book Club"],
)
@@ -149,8 +151,8 @@ RSpec.describe HashtagAutocompleteService do
category6 = Fabricate(:category, name: "Book Reviews", slug: "book-reviews")
Fabricate(:category, name: "Good Books", slug: "book", parent_category: category6)
- Fabricate(:tag, name: "bookmania", topic_count: 15)
- Fabricate(:tag, name: "awful-books", topic_count: 56)
+ Fabricate(:tag, name: "bookmania", staff_topic_count: 15, public_topic_count: 15)
+ Fabricate(:tag, name: "awful-books", staff_topic_count: 56, public_topic_count: 56)
expect(subject.search("book", %w[category tag]).map(&:ref)).to eq(
[
@@ -220,9 +222,13 @@ RSpec.describe HashtagAutocompleteService do
end
fab!(:category4) { Fabricate(:category, name: "Bookworld", slug: "book", topic_count: 56) }
fab!(:category5) { Fabricate(:category, name: "Media", slug: "media", topic_count: 446) }
- fab!(:tag2) { Fabricate(:tag, name: "mid-books", topic_count: 33) }
- fab!(:tag3) { Fabricate(:tag, name: "terrible-books", topic_count: 2) }
- fab!(:tag4) { Fabricate(:tag, name: "book", topic_count: 1) }
+ fab!(:tag2) do
+ Fabricate(:tag, name: "mid-books", staff_topic_count: 33, public_topic_count: 33)
+ end
+ fab!(:tag3) do
+ Fabricate(:tag, name: "terrible-books", staff_topic_count: 2, public_topic_count: 2)
+ end
+ fab!(:tag4) { Fabricate(:tag, name: "book", staff_topic_count: 1, public_topic_count: 1) }
it "returns the 'most polular' categories and tags (based on topic_count) that the user can access" do
category1.update!(read_restricted: true)
diff --git a/spec/services/tag_hashtag_data_source_spec.rb b/spec/services/tag_hashtag_data_source_spec.rb
index 3598c664f95..f1475973ac8 100644
--- a/spec/services/tag_hashtag_data_source_spec.rb
+++ b/spec/services/tag_hashtag_data_source_spec.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
RSpec.describe TagHashtagDataSource do
- fab!(:tag1) { Fabricate(:tag, name: "fact", topic_count: 0) }
- fab!(:tag2) { Fabricate(:tag, name: "factor", topic_count: 5) }
- fab!(:tag3) { Fabricate(:tag, name: "factory", topic_count: 4) }
- fab!(:tag4) { Fabricate(:tag, name: "factorio", topic_count: 3) }
- fab!(:tag5) { Fabricate(:tag, name: "factz", topic_count: 1) }
+ fab!(:tag1) { Fabricate(:tag, name: "fact", public_topic_count: 0) }
+ fab!(:tag2) { Fabricate(:tag, name: "factor", public_topic_count: 5) }
+ fab!(:tag3) { Fabricate(:tag, name: "factory", public_topic_count: 4) }
+ fab!(:tag4) { Fabricate(:tag, name: "factorio", public_topic_count: 3) }
+ fab!(:tag5) { Fabricate(:tag, name: "factz", public_topic_count: 1) }
fab!(:user) { Fabricate(:user) }
let(:guardian) { Guardian.new(user) }
describe "#search" do
- it "orders tag results by exact search match, then topic count, then name" do
+ it "orders tag results by exact search match, then public topic count, then name" do
expect(described_class.search(guardian, "fact", 5).map(&:slug)).to eq(
%w[fact factor factory factorio factz],
)
@@ -31,7 +31,7 @@ RSpec.describe TagHashtagDataSource do
)
end
- it "includes the topic count for the text of the tag in secondary text" do
+ it "includes the public topic count for the text of the tag in secondary text" do
expect(described_class.search(guardian, "fact", 5).map(&:secondary_text)).to eq(
%w[x0 x5 x4 x3 x1],
)
@@ -52,7 +52,7 @@ RSpec.describe TagHashtagDataSource do
end
describe "#search_without_term" do
- it "returns distinct tags sorted by topic_count" do
+ it "returns distinct tags sorted by public topic count" do
expect(described_class.search_without_term(guardian, 5).map(&:slug)).to eq(
%w[factor factory factorio factz fact],
)
diff --git a/spec/support/user_sidebar_serializer_attributes.rb b/spec/support/user_sidebar_serializer_attributes.rb
index f7cea951b34..9bf6eaa5d5c 100644
--- a/spec/support/user_sidebar_serializer_attributes.rb
+++ b/spec/support/user_sidebar_serializer_attributes.rb
@@ -65,7 +65,9 @@ RSpec.shared_examples "User Sidebar Serializer Attributes" do |serializer_klass|
describe "#sidebar_tags" do
fab!(:tag) { Fabricate(:tag, name: "foo") }
- fab!(:pm_tag) { Fabricate(:tag, name: "bar", pm_topic_count: 5, topic_count: 0) }
+ fab!(:pm_tag) do
+ Fabricate(:tag, name: "bar", pm_topic_count: 5, staff_topic_count: 0, public_topic_count: 0)
+ end
fab!(:hidden_tag) { Fabricate(:tag, name: "secret") }
fab!(:staff_tag_group) do
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: ["secret"])
diff --git a/spec/system/hashtag_autocomplete_spec.rb b/spec/system/hashtag_autocomplete_spec.rb
index 131c19d32fc..254f6a686c7 100644
--- a/spec/system/hashtag_autocomplete_spec.rb
+++ b/spec/system/hashtag_autocomplete_spec.rb
@@ -10,8 +10,8 @@ describe "Using #hashtag autocompletion to search for and lookup categories and
fab!(:category2) do
Fabricate(:category, name: "Other Category", slug: "other-cat", topic_count: 23)
end
- fab!(:tag) { Fabricate(:tag, name: "cooltag", topic_count: 324) }
- fab!(:tag2) { Fabricate(:tag, name: "othertag", topic_count: 66) }
+ fab!(:tag) { Fabricate(:tag, name: "cooltag", staff_topic_count: 324, public_topic_count: 324) }
+ fab!(:tag2) { Fabricate(:tag, name: "othertag", staff_topic_count: 66, public_topic_count: 66) }
fab!(:topic) { Fabricate(:topic, category: category, tags: [tag]) }
fab!(:post) { Fabricate(:post, topic: topic) }
let(:uncategorized_category) { Category.find(SiteSetting.uncategorized_category_id) }