1
0
Fork 0
discourse-custom-wizard-unl.../lib/custom_wizard/mapper.rb

214 Zeilen
4,6 KiB
Ruby

2020-03-30 08:16:03 +02:00
class CustomWizard::Mapper
attr_accessor :inputs, :data, :user
2020-04-10 10:51:01 +02:00
USER_FIELDS = ['name', 'username', 'email', 'date_of_birth', 'title', 'locale', 'trust_level']
2020-03-30 08:16:03 +02:00
PROFILE_FIELDS = ['location', 'website', 'bio_raw']
2020-04-07 15:33:11 +02:00
def self.user_fields
USER_FIELDS + PROFILE_FIELDS
end
2020-04-01 07:03:26 +02:00
OPERATORS = {
2020-04-01 14:16:26 +02:00
equal: '==',
2020-04-01 07:03:26 +02:00
greater: '>',
less: '<',
greater_or_equal: '>=',
2020-04-06 10:36:38 +02:00
less_or_equal: '<=',
regex: '=~'
2020-04-01 07:03:26 +02:00
}
2020-03-30 08:16:03 +02:00
def initialize(params)
@inputs = params[:inputs] || {}
@data = params[:data] || {}
@user = params[:user]
@opts = params[:opts] || {}
end
2020-04-06 10:36:38 +02:00
def perform
2020-03-30 08:16:03 +02:00
multiple = @opts[:multiple]
2020-04-06 10:36:38 +02:00
perform_result = multiple ? [] : nil
2020-03-30 08:16:03 +02:00
inputs.each do |input|
2020-04-06 10:36:38 +02:00
input_type = input['type']
pairs = input['pairs']
if (input_type === 'conditional' && validate_pairs(pairs)) || input_type === 'assignment'
output = input['output']
output_type = input['output_type']
result = build_result(map_field(output, output_type), input_type)
2020-03-30 08:16:03 +02:00
if multiple
2020-04-06 10:36:38 +02:00
perform_result.push(result)
2020-03-30 08:16:03 +02:00
else
2020-04-06 10:36:38 +02:00
perform_result = result
2020-03-30 08:16:03 +02:00
break
end
end
2020-04-06 10:36:38 +02:00
if input_type === 'validation'
result = build_result(validate_pairs(pairs), input_type)
2020-03-30 08:16:03 +02:00
2020-04-06 10:36:38 +02:00
if multiple
perform_result.push(result)
2020-03-30 08:16:03 +02:00
else
2020-04-06 10:36:38 +02:00
perform_result = result
break
end
end
if input_type === 'association'
result = build_result(map_pairs(pairs), input_type)
if multiple
perform_result.push(result)
else
perform_result = result
2020-03-30 08:16:03 +02:00
break
end
end
end
2020-04-07 10:33:51 +02:00
2020-04-06 10:36:38 +02:00
perform_result
end
def build_result(result, type)
2020-04-07 09:54:30 +02:00
if @opts[:with_type]
2020-04-06 10:36:38 +02:00
{
type: type,
result: result
}
else
result
end
2020-03-30 08:16:03 +02:00
end
def validate_pairs(pairs)
failed = false
pairs.each do |pair|
key = map_field(pair['key'], pair['key_type'])
2020-04-07 09:54:30 +02:00
connector = pair['connector']
operator = map_operator(connector)
2020-04-07 13:53:00 +02:00
value = cast_value(
key,
interpolate(map_field(pair['value'], pair['value_type'])),
connector
)
2020-04-07 09:54:30 +02:00
2020-04-01 07:03:26 +02:00
begin
2020-04-07 09:54:30 +02:00
failed = !cast_result(key.public_send(operator, value), connector)
2020-04-01 14:16:26 +02:00
rescue NoMethodError
#
2020-04-01 07:03:26 +02:00
end
2020-03-30 08:16:03 +02:00
end
!failed
end
2020-04-07 13:53:00 +02:00
def cast_value(key, value, connector)
if connector == 'regex'
Regexp.new(value)
else
if key.is_a?(String)
value.to_s
elsif key.is_a?(Integer)
value.to_i
else
value
end
end
end
2020-04-07 09:54:30 +02:00
def cast_result(result, connector)
if connector == 'regex'
result == 0 ? true : false
else
result
end
end
2020-04-06 10:36:38 +02:00
def map_pairs(pairs)
result = []
pairs.each do |pair|
key = map_field(pair['key'], pair['key_type'])
value = map_field(pair['value'], pair['value_type'])
if key && value
result.push(
key: key,
value: value
)
end
end
result
end
def map_operator(connector)
2020-04-01 07:03:26 +02:00
OPERATORS[connector.to_sym] || '=='
2020-03-30 08:16:03 +02:00
end
def map_field(value, type)
2020-04-02 10:21:03 +02:00
method = "map_#{type}"
2020-03-30 08:16:03 +02:00
if self.respond_to?(method)
self.send(method, value)
else
value
end
end
2020-04-13 14:17:22 +02:00
def map_text(value)
interpolate(value)
end
2020-04-07 10:33:51 +02:00
def map_wizard_field(value)
2020-03-30 08:16:03 +02:00
data && !data.key?("submitted_at") && data[value]
end
2020-04-02 10:21:03 +02:00
def map_user_field(value)
2020-03-30 08:16:03 +02:00
if value.include?('user_field_')
UserCustomField.where(user_id: user.id, name: value).pluck(:value).first
elsif PROFILE_FIELDS.include?(value)
UserProfile.find_by(user_id: user.id).send(value)
elsif USER_FIELDS.include?(value)
User.find(user.id).send(value)
end
end
def interpolate(string)
2020-04-16 05:33:42 +02:00
string.gsub!(/u\{(.*?)\}/) do |match|
2020-03-30 08:16:03 +02:00
result = ''
result = user.send($1) if USER_FIELDS.include?($1)
result = user.user_profile.send($1) if PROFILE_FIELDS.include?($1)
result
end
2020-04-16 05:33:42 +02:00
string.gsub(/v\{(.*?)\}/) do |match|
2020-03-30 08:16:03 +02:00
attrs = $1.split(':')
key = attrs.first
2020-04-16 05:33:42 +02:00
value = data[key]
format = attrs.last if attrs.length > 1
result = nil
2020-03-30 08:16:03 +02:00
if key == 'time'
2020-04-16 05:33:42 +02:00
time_format = value.present? ? value : "%B %-d, %Y"
return Time.now.strftime(time_format)
end
if value.present?
return recurse(value, [*$1.split('.')])
2020-03-30 08:16:03 +02:00
end
2020-04-16 05:33:42 +02:00
result
2020-03-30 08:16:03 +02:00
end
end
def recurse(data, keys)
k = keys.shift
result = data[k]
keys.empty? ? result : self.recurse(result, keys)
end
end