discourse/lib/theme_settings_manager.rb
Osama Sayegh 2215fa0c8e
FIX: Pass values of objects typed settings to theme migrations (#26751)
This commit fixes a bug in theme settings migrations where values of `objects` typed theme settings aren't passed to migrations even when there are overriding values for those settings. What causes this bug is that, when creating the hash that contains all the overridden settings and will be passed to migrations, the values of `objects` typed settings are incorrectly retrieved from the `value` column (which is always nil for `objects` type) instead of `json_value`. `objects` settings are different from all other types in that they store their values in the `json_value` column and they need to be special-cased when retrieving their values.
2024-04-25 16:39:22 +03:00

106 lines
2.4 KiB
Ruby

# frozen_string_literal: true
class ThemeSettingsManager
attr_reader :name, :theme, :default
def self.types
ThemeSetting.types
end
def self.cast_row_value(row)
type_name = self.types.invert[row.data_type].downcase.capitalize
klass = "ThemeSettingsManager::#{type_name}".constantize
klass.cast(klass.extract_value_from_row(row))
end
def self.create(name, default, type, theme, opts = {})
type_name = self.types.invert[type].downcase.capitalize
klass = "ThemeSettingsManager::#{type_name}".constantize
klass.new(name, default, theme, opts)
end
def self.cast(value)
value
end
def self.extract_value_from_row(row)
row.value
end
def initialize(name, default, theme, opts = {})
@name = name.to_sym
@default = default
@theme = theme
@opts = opts
@types = self.class.types
end
def value
has_record? ? db_record.value : default
end
def type_name
self.class.name.demodulize.downcase.to_sym
end
def type
@types[type_name]
end
def description
@opts[:description] # Old method of specifying description. Is now overridden by locale file
end
def requests_refresh?
@opts[:refresh]
end
def value=(new_value)
ensure_is_valid_value!(new_value)
value = new_value.to_s
record = has_record? ? update_record!(value:) : create_record!(value:)
record.value
end
def db_record
# theme.theme_settings will already be preloaded, so it is better to use
# `find` on an array, rather than make a round trip to the database
theme.theme_settings.to_a.find do |i|
i.name.to_s == @name.to_s && i.data_type.to_s == type.to_s
end
end
def update_record!(args)
db_record.tap { |instance| instance.update!(args) }
end
def create_record!(args)
record = ThemeSetting.new(name: @name, data_type: type, theme: @theme, **args)
record.save!
record
end
def has_record?
db_record.present?
end
def ensure_is_valid_value!(new_value)
return if new_value.nil?
error_messages = ThemeSettingsValidator.validate_value(new_value, type, @opts)
raise Discourse::InvalidParameters.new error_messages.join(" ") if error_messages.present?
end
def has_min?
min = @opts[:min]
(min.is_a?(::Integer) || min.is_a?(::Float)) && min != -::Float::INFINITY
end
def has_max?
max = @opts[:max]
(max.is_a?(::Integer) || max.is_a?(::Float)) && max != ::Float::INFINITY
end
end