117 lines
3.9 KiB
Ruby
117 lines
3.9 KiB
Ruby
module DiscourseTagging
|
|
|
|
TAGS_FIELD_NAME = "tags"
|
|
TAGS_FILTER_REGEXP = /[<\\\/\>\#\?\&\s]/
|
|
|
|
# class Engine < ::Rails::Engine
|
|
# engine_name "discourse_tagging"
|
|
# isolate_namespace DiscourseTagging
|
|
# end
|
|
|
|
def self.clean_tag(tag)
|
|
tag.downcase.strip[0...SiteSetting.max_tag_length].gsub(TAGS_FILTER_REGEXP, '')
|
|
end
|
|
|
|
def self.staff_only_tags(tags)
|
|
return nil if tags.nil?
|
|
|
|
staff_tags = SiteSetting.staff_tags.split("|")
|
|
|
|
tag_diff = tags - staff_tags
|
|
tag_diff = tags - tag_diff
|
|
|
|
tag_diff.present? ? tag_diff : nil
|
|
end
|
|
|
|
def self.tags_for_saving(tags, guardian)
|
|
|
|
return [] unless guardian.can_tag_topics?
|
|
|
|
return unless tags.present?
|
|
|
|
tags.map! {|t| clean_tag(t) }
|
|
tags.delete_if {|t| t.blank? }
|
|
tags.uniq!
|
|
|
|
# If the user can't create tags, remove any tags that don't already exist
|
|
# TODO: this is doing a full count, it should just check first or use a cache
|
|
unless guardian.can_create_tag?
|
|
tag_count = TopicCustomField.where(name: TAGS_FIELD_NAME, value: tags).group(:value).count
|
|
tags.delete_if {|t| !tag_count.has_key?(t) }
|
|
end
|
|
|
|
return tags[0...SiteSetting.max_tags_per_topic]
|
|
end
|
|
|
|
def self.notification_key(tag_id)
|
|
"tags_notification:#{tag_id}"
|
|
end
|
|
|
|
def self.auto_notify_for(tags, topic)
|
|
# This insert will run up to SiteSetting.max_tags_per_topic times
|
|
tags.each do |tag|
|
|
key_name_sql = ActiveRecord::Base.sql_fragment("('#{notification_key(tag)}')", tag)
|
|
|
|
sql = <<-SQL
|
|
INSERT INTO topic_users(user_id, topic_id, notification_level, notifications_reason_id)
|
|
SELECT ucf.user_id,
|
|
#{topic.id.to_i},
|
|
CAST(ucf.value AS INTEGER),
|
|
#{TopicUser.notification_reasons[:plugin_changed]}
|
|
FROM user_custom_fields AS ucf
|
|
WHERE ucf.name IN #{key_name_sql}
|
|
AND NOT EXISTS(SELECT 1 FROM topic_users WHERE topic_id = #{topic.id.to_i} AND user_id = ucf.user_id)
|
|
AND CAST(ucf.value AS INTEGER) <> #{TopicUser.notification_levels[:regular]}
|
|
SQL
|
|
|
|
ActiveRecord::Base.exec_sql(sql)
|
|
end
|
|
end
|
|
|
|
def self.rename_tag(current_user, old_id, new_id)
|
|
sql = <<-SQL
|
|
UPDATE topic_custom_fields AS tcf
|
|
SET value = :new_id
|
|
WHERE value = :old_id
|
|
AND name = :tags_field_name
|
|
AND NOT EXISTS(SELECT 1
|
|
FROM topic_custom_fields
|
|
WHERE value = :new_id AND name = :tags_field_name AND topic_id = tcf.topic_id)
|
|
SQL
|
|
|
|
user_sql = <<-SQL
|
|
UPDATE user_custom_fields
|
|
SET name = :new_user_tag_id
|
|
WHERE name = :old_user_tag_id
|
|
AND NOT EXISTS(SELECT 1
|
|
FROM user_custom_fields
|
|
WHERE name = :new_user_tag_id)
|
|
SQL
|
|
|
|
ActiveRecord::Base.transaction do
|
|
ActiveRecord::Base.exec_sql(sql, new_id: new_id, old_id: old_id, tags_field_name: TAGS_FIELD_NAME)
|
|
TopicCustomField.delete_all(name: TAGS_FIELD_NAME, value: old_id)
|
|
ActiveRecord::Base.exec_sql(user_sql, new_user_tag_id: notification_key(new_id),
|
|
old_user_tag_id: notification_key(old_id))
|
|
UserCustomField.delete_all(name: notification_key(old_id))
|
|
StaffActionLogger.new(current_user).log_custom('renamed_tag', previous_value: old_id, new_value: new_id)
|
|
end
|
|
end
|
|
|
|
def self.top_tags(limit_arg=nil)
|
|
# TODO: cache
|
|
# TODO: need an index for this (name,value)
|
|
TopicCustomField.where(name: TAGS_FIELD_NAME)
|
|
.group(:value)
|
|
.limit(limit_arg || SiteSetting.max_tags_in_filter_list)
|
|
.order('COUNT(value) DESC')
|
|
.count
|
|
.map {|name, count| name}
|
|
end
|
|
|
|
def self.muted_tags(user)
|
|
return [] unless user
|
|
UserCustomField.where(user_id: user.id, value: TopicUser.notification_levels[:muted]).pluck(:name).map { |x| x[0,17] == "tags_notification" ? x[18..-1] : nil}.compact
|
|
end
|
|
end
|