1
0
Fork 0
discourse-custom-wizard-unl.../lib/custom_wizard/validators/update.rb
2022-03-16 12:33:34 +01:00

134 Zeilen
3,5 KiB
Ruby

# frozen_string_literal: true
require 'addressable/uri'
class ::CustomWizard::UpdateValidator
attr_reader :updater
def initialize(updater)
@updater = updater
end
def perform
updater.step.fields.each do |field|
validate_field(field)
end
end
def validate_field(field)
return if field.type == 'text_only'
field_id = field.id.to_s
value = @updater.submission[field_id]
min_length = false
label = field.raw[:label]
type = field.type
required = field.required
min_length = field.min_length if is_text_type(field)
max_length = field.max_length if is_text_type(field)
file_types = field.file_types
format = field.format
if required && !value
@updater.errors.add(field_id, I18n.t('wizard.field.required', label: label))
end
if value.is_a?(String) && (stripped_length = value.strip.length) > 0
if min_length.present? && stripped_length < min_length.to_i
@updater.errors.add(field_id, I18n.t('wizard.field.too_short', label: label, min: min_length.to_i))
end
if max_length.present? && stripped_length > max_length.to_i
@updater.errors.add(field_id, I18n.t('wizard.field.too_long', label: label, max: max_length.to_i))
end
end
if is_url_type(field) && value.present? && !check_if_url(value)
@updater.errors.add(field_id, I18n.t('wizard.field.not_url', label: label))
end
if type === 'checkbox'
@updater.submission[field_id] = standardise_boolean(value)
end
if type === 'upload' && value.present? && !validate_file_type(value, file_types)
@updater.errors.add(field_id, I18n.t('wizard.field.invalid_file', label: label, types: file_types))
end
if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value, format)
@updater.errors.add(field_id, I18n.t('wizard.field.invalid_date'))
end
if type === 'time' && value.present? && !validate_time(value)
@updater.errors.add(field_id, I18n.t('wizard.field.invalid_time'))
end
self.class.field_validators.each do |validator|
if type === validator[:type]
validator[:block].call(field, value, @updater)
end
end
end
def self.sorted_field_validators
@sorted_field_validators ||= []
end
def self.field_validators
sorted_field_validators.map { |h| { type: h[:type], block: h[:block] } }
end
def self.add_field_validator(priority = 0, type, &block)
sorted_field_validators << { priority: priority, type: type, block: block }
@sorted_field_validators.sort_by! { |h| -h[:priority] }
end
private
def validate_file_type(value, file_types)
file_types.split(',')
.map { |t| t.gsub('.', '') }
.include?(File.extname(value['original_filename'])[1..-1])
end
def validate_date(value, format)
v8.eval("moment('#{value}', '#{format}', true).isValid()")
end
def validate_time(value)
begin
Time.parse(value)
true
rescue ArgumentError
false
end
end
def is_text_type(field)
['text', 'textarea', 'composer'].include? field.type
end
def is_url_type(field)
['url'].include? field.type
end
SCHEMES ||= %w(http https)
def check_if_url(url)
parsed = Addressable::URI.parse(url) or return false
SCHEMES.include?(parsed.scheme)
rescue Addressable::URI::InvalidURIError
false
end
def standardise_boolean(value)
ActiveRecord::Type::Boolean.new.cast(value)
end
def v8
return @ctx if @ctx
@ctx = PrettyText.v8
PrettyText.ctx_load(@ctx, "#{Rails.root}/vendor/assets/javascripts/moment.js")
@ctx
end
end