0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-25 18:50:27 +01:00
discourse-custom-wizard/lib/custom_wizard/custom_field.rb

173 Zeilen
Kein EOL
3,9 KiB
Ruby

# frozen_string_literal: true
class ::CustomWizard::CustomField
include HasErrors
include ActiveModel::Serialization
attr_reader :id
ATTRS ||= ["name", "klass", "type", "serializers"]
REQUIRED ||= ["name", "klass"]
NAMESPACE ||= "custom_wizard_custom_fields"
NAME_MIN_LENGTH ||= 3
CLASSES ||= {
topic: ["topic_view", "topic_list_item"],
group: ["basic_group"],
category: ["basic_category"],
post: ["post"]
}
TYPES ||= ["string", "boolean", "integer", "json"]
def self.serializers
CLASSES.values.flatten.uniq
end
def initialize(id, data)
@id = id
data = data.with_indifferent_access
ATTRS.each do |attr|
self.class.class_eval { attr_accessor attr }
value = data[attr]
if value.present?
send("#{attr}=", value)
end
end
end
def save
validate
if valid?
data = {}
key = name
(ATTRS - ['name']).each do |attr|
data[attr] = send(attr)
end
if self.class.save_to_store(id, key, data)
self.class.reset
true
else
false
end
else
false
end
end
def validate
ATTRS.each do |attr|
value = send(attr)
i18n_key = "wizard.custom_field.error"
if REQUIRED.include?(attr) && value.blank?
I18n.t("#{i18n_key}.required_attribute", attr: attr)
next
end
if (attr == 'klass' && CLASSES.keys.exclude?(value.to_sym)) ||
(attr == 'serializers' && CLASSES[klass.to_sym].blank?)
add_error(I18n.t("#{i18n_key}.unsupported_class", class: value))
next
end
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
add_error(I18n.t("#{i18n_key}.unsupported_serializers",
class: klass,
serializers: unsupported.join(", ")
))
end
if attr == 'type' && TYPES.exclude?(value)
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
end
if attr == 'name'
unless value.is_a?(String)
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
end
if value.length < NAME_MIN_LENGTH
add_error(I18n.t("#{i18n_key}.name_too_short", name: value, min_length: NAME_MIN_LENGTH))
end
if new? && self.class.exists?(name)
add_error(I18n.t("#{i18n_key}.name_already_taken", name: value))
end
begin
@name = value.parameterize(separator: '_')
rescue
add_error(I18n.t("#{i18n_key}.name_invalid", name: value))
end
end
end
end
def new?
id.blank?
end
def valid?
errors.blank?
end
def self.reset
@list = nil
end
def self.list
@list ||= PluginStoreRow.where(plugin_name: NAMESPACE)
.map { |record| create_from_store(record) }
end
def self.list_by(attr, value)
self.list.select do |cf|
if attr == :serializers
cf.send(attr).include?(value)
else
cf.send(attr) == value
end
end
end
def self.exists?(name)
PluginStoreRow.where(plugin_name: NAMESPACE, key: name).exists?
end
def self.find(name)
records = PluginStoreRow.where(plugin_name: NAMESPACE, key: name)
if records.exists?
create_from_store(records.first)
else
false
end
end
def self.create_from_store(record)
data = JSON.parse(record.value)
data[:name] = record.key
new(record.id, data)
end
def self.save_to_store(id = nil, key, data)
if id
record = PluginStoreRow.find_by(id: id, plugin_name: NAMESPACE, key: key)
return false if !record
record.value = data.to_json
record.save
else
record = PluginStoreRow.new(plugin_name: NAMESPACE, key: key)
record.type_name = "JSON"
record.value = data.to_json
record.save
end
end
end