discourse/lib/seed_data/categories.rb

179 lines
5.3 KiB
Ruby

# frozen_string_literal: true
module SeedData
class Categories
def self.with_default_locale
SeedData::Categories.new(SiteSetting.default_locale)
end
def initialize(locale)
@locale = locale
end
def create(site_setting_names: nil)
I18n.with_locale(@locale) do
categories(site_setting_names).each { |params| create_category(**params) }
end
end
def update(site_setting_names: nil, skip_changed: false)
I18n.with_locale(@locale) do
categories(site_setting_names).each do |params|
params.slice!(:site_setting_name, :name, :description)
params[:skip_changed] = skip_changed
update_category(**params)
end
end
end
def reseed_options
I18n.with_locale(@locale) do
categories.map do |params|
category = find_category(params[:site_setting_name])
next unless category
{
id: params[:site_setting_name],
name: category.name,
selected: unchanged?(category)
}
end.compact
end
end
private
def categories(site_setting_names = nil)
categories = [
{
site_setting_name: 'uncategorized_category_id',
name: I18n.t('uncategorized_category_name'),
description: nil,
position: 0,
color: '0088CC',
text_color: 'FFFFFF',
permissions: { everyone: :full },
force_permissions: true,
force_existence: true
},
{
site_setting_name: 'meta_category_id',
name: I18n.t('meta_category_name'),
description: I18n.t('meta_category_description'),
position: 1,
color: '808281',
text_color: 'FFFFFF',
permissions: { everyone: :full },
force_permissions: true
},
{
site_setting_name: 'staff_category_id',
name: I18n.t('staff_category_name'),
description: I18n.t('staff_category_description'),
position: 2,
color: 'E45735',
text_color: 'FFFFFF',
permissions: { staff: :full },
force_permissions: true
},
{
site_setting_name: 'general_category_id',
name: I18n.t('general_category_name'),
description: I18n.t('general_category_description'),
position: 3,
color: '25AAE2',
text_color: 'FFFFFF',
permissions: { everyone: :full },
force_permissions: true
}
]
if site_setting_names
categories.select! { |c| site_setting_names.include?(c[:site_setting_name]) }
end
categories
end
def create_category(site_setting_name:, name:, description:, position:, color:, text_color:,
permissions:, force_permissions:, force_existence: false)
category_id = SiteSetting.get(site_setting_name)
if should_create_category?(category_id, force_existence)
category = Category.new(
name: unused_category_name(category_id, name),
description: description,
user_id: Discourse::SYSTEM_USER_ID,
position: position,
color: color,
text_color: text_color
)
category.skip_category_definition = true if description.blank?
category.set_permissions(permissions)
category.save!
SiteSetting.set(site_setting_name, category.id)
elsif category = Category.find_by(id: category_id)
if description.present? && (category.topic_id.blank? || !Topic.exists?(category.topic_id))
category.description = description
category.create_category_definition
end
if force_permissions
category.set_permissions(permissions)
category.save!(validate: false) if category.changed?
end
end
end
def should_create_category?(category_id, force_existence)
return false if User.human_users.any?
if category_id > 0
force_existence ? !Category.exists?(category_id) : false
else
true
end
end
def unused_category_name(category_id, name)
category_exists = Category.where(
'id <> :id AND LOWER(name) = :name',
id: category_id,
name: name.downcase
).exists?
category_exists ? "#{name}#{SecureRandom.hex}" : name
end
def update_category(site_setting_name:, name:, description:, skip_changed:)
category = find_category(site_setting_name)
return if !category || (skip_changed && !unchanged?(category))
name = unused_category_name(category.id, name)
category.name = name
category.slug = Slug.for(name, '')
category.save!
if description.present? && description_post = category&.topic&.first_post
changes = { title: I18n.t("category.topic_prefix", category: name), raw: description }
description_post.revise(Discourse.system_user, changes, skip_validations: true)
end
end
def find_category(site_setting_name)
category_id = SiteSetting.get(site_setting_name)
Category.find_by(id: category_id) if category_id > 0
end
def unchanged?(category)
if description_post = category&.topic&.first_post
return description_post.last_editor_id == Discourse::SYSTEM_USER_ID
end
true
end
end
end