diff --git a/lib/theme_settings_manager.rb b/lib/theme_settings_manager.rb index 997ae92a538..749e6ebdef6 100644 --- a/lib/theme_settings_manager.rb +++ b/lib/theme_settings_manager.rb @@ -112,155 +112,4 @@ class ThemeSettingsManager max = @opts[:max] (max.is_a?(::Integer) || max.is_a?(::Float)) && max != ::Float::INFINITY end - - class Objects < self - def value - has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys) - end - - def value=(objects) - # TODO: Validate the objects against the schema - - record = has_record? ? db_record : create_record! - record.json_value = objects - record.save! - record.json_value - end - end - - class List < self - def list_type - @opts[:list_type] - end - end - - class String < self - def is_valid_value?(new_value) - (@opts[:min]..@opts[:max]).include? new_value.to_s.length - end - - def textarea - @opts[:textarea] - end - - def json_schema - begin - JSON.parse(@opts[:json_schema]) - rescue StandardError - false - end - end - end - - class Bool < self - def self.cast(value) - [true, "true"].include?(value) - end - - def value - self.class.cast(super) - end - - def value=(new_value) - new_value = (self.class.cast(new_value)).to_s - super(new_value) - end - end - - class Integer < self - def self.cast(value) - value.to_i - end - - def value - self.class.cast(super) - end - - def value=(new_value) - super(self.class.cast(new_value)) - end - - def is_valid_value?(new_value) - (@opts[:min]..@opts[:max]).include? new_value.to_i - end - end - - class Float < self - def self.cast(value) - value.to_f - end - - def value - self.class.cast(super) - end - - def value=(new_value) - super(self.class.cast(new_value)) - end - - def is_valid_value?(new_value) - (@opts[:min]..@opts[:max]).include? new_value.to_f - end - end - - class Enum < self - def value - val = super - match = choices.find { |choice| choice == val || choice.to_s == val } - match || val - end - - def is_valid_value?(new_value) - choices.include?(new_value) || choices.map(&:to_s).include?(new_value) - end - - def choices - @opts[:choices] - end - end - - class Upload < self - def value - has_record? ? cdn_url(db_record.value) : default - end - - def default - upload_id = default_upload_id - return if upload_id.blank? - - cdn_url(upload_id) - end - - def value=(new_value) - if new_value.present? - if new_value == default - new_value = default_upload_id - else - upload = ::Upload.find_by(url: new_value) - new_value = upload.id if upload.present? - end - end - - super(new_value) - end - - private - - def cdn_url(upload_id) - return if upload_id.blank? - - upload = ::Upload.find_by_id(upload_id.to_i) - return if upload.blank? - - Discourse.store.cdn_url(upload.url) - end - - def default_upload_id - theme_field = - theme.theme_fields.find_by(name: @default, type_id: ThemeField.types[:theme_upload_var]) - return if theme_field.blank? - - theme_field.upload_id - end - end end diff --git a/lib/theme_settings_manager/bool.rb b/lib/theme_settings_manager/bool.rb new file mode 100644 index 00000000000..b2b8c4c87ad --- /dev/null +++ b/lib/theme_settings_manager/bool.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Bool < ThemeSettingsManager + def self.cast(value) + [true, "true"].include?(value) + end + + def value + self.class.cast(super) + end + + def value=(new_value) + new_value = (self.class.cast(new_value)).to_s + super(new_value) + end +end diff --git a/lib/theme_settings_manager/enum.rb b/lib/theme_settings_manager/enum.rb new file mode 100644 index 00000000000..4dffe3d3705 --- /dev/null +++ b/lib/theme_settings_manager/enum.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Enum < ThemeSettingsManager + def value + val = super + match = choices.find { |choice| choice == val || choice.to_s == val } + match || val + end + + def is_valid_value?(new_value) + choices.include?(new_value) || choices.map(&:to_s).include?(new_value) + end + + def choices + @opts[:choices] + end +end diff --git a/lib/theme_settings_manager/float.rb b/lib/theme_settings_manager/float.rb new file mode 100644 index 00000000000..d33bc71de2e --- /dev/null +++ b/lib/theme_settings_manager/float.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Float < ThemeSettingsManager + def self.cast(value) + value.to_f + end + + def value + self.class.cast(super) + end + + def value=(new_value) + super(self.class.cast(new_value)) + end + + def is_valid_value?(new_value) + (@opts[:min]..@opts[:max]).include? new_value.to_f + end +end diff --git a/lib/theme_settings_manager/integer.rb b/lib/theme_settings_manager/integer.rb new file mode 100644 index 00000000000..615b93f63ae --- /dev/null +++ b/lib/theme_settings_manager/integer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Integer < ThemeSettingsManager + def self.cast(value) + value.to_i + end + + def value + self.class.cast(super) + end + + def value=(new_value) + super(self.class.cast(new_value)) + end + + def is_valid_value?(new_value) + (@opts[:min]..@opts[:max]).include? new_value.to_i + end +end diff --git a/lib/theme_settings_manager/list.rb b/lib/theme_settings_manager/list.rb new file mode 100644 index 00000000000..0a83bee35e5 --- /dev/null +++ b/lib/theme_settings_manager/list.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::List < ThemeSettingsManager + def list_type + @opts[:list_type] + end +end diff --git a/lib/theme_settings_manager/objects.rb b/lib/theme_settings_manager/objects.rb new file mode 100644 index 00000000000..50a7b730ef0 --- /dev/null +++ b/lib/theme_settings_manager/objects.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Objects < ThemeSettingsManager + def value + has_record? ? db_record.json_value : default.map!(&:deep_stringify_keys) + end + + def value=(objects) + # TODO: Validate the objects against the schema + + record = has_record? ? db_record : create_record! + record.json_value = objects + record.save! + theme.reload + record.json_value + end +end diff --git a/lib/theme_settings_manager/string.rb b/lib/theme_settings_manager/string.rb new file mode 100644 index 00000000000..14928c83d0d --- /dev/null +++ b/lib/theme_settings_manager/string.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::String < ThemeSettingsManager + def is_valid_value?(new_value) + (@opts[:min]..@opts[:max]).include? new_value.to_s.length + end + + def textarea + @opts[:textarea] + end + + def json_schema + begin + JSON.parse(@opts[:json_schema]) + rescue StandardError + false + end + end +end diff --git a/lib/theme_settings_manager/upload.rb b/lib/theme_settings_manager/upload.rb new file mode 100644 index 00000000000..301ae2e9d63 --- /dev/null +++ b/lib/theme_settings_manager/upload.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +class ThemeSettingsManager::Upload < ThemeSettingsManager + def value + has_record? ? cdn_url(db_record.value) : default + end + + def default + upload_id = default_upload_id + return if upload_id.blank? + + cdn_url(upload_id) + end + + def value=(new_value) + if new_value.present? + if new_value == default + new_value = default_upload_id + else + upload = ::Upload.find_by(url: new_value) + new_value = upload.id if upload.present? + end + end + + super(new_value) + end + + private + + def cdn_url(upload_id) + return if upload_id.blank? + + upload = ::Upload.find_by_id(upload_id.to_i) + return if upload.blank? + + Discourse.store.cdn_url(upload.url) + end + + def default_upload_id + theme_field = + theme.theme_fields.find_by(name: @default, type_id: ThemeField.types[:theme_upload_var]) + return if theme_field.blank? + + theme_field.upload_id + end +end diff --git a/spec/fixtures/theme_settings/valid_settings.yaml b/spec/fixtures/theme_settings/valid_settings.yaml index e212f6e74b3..4c3e3b480d4 100644 --- a/spec/fixtures/theme_settings/valid_settings.yaml +++ b/spec/fixtures/theme_settings/valid_settings.yaml @@ -84,16 +84,3 @@ valid_json_schema_setting: causes_refresh: default: "" refresh: true - -valid_objects_setting: - type: objects - default: - - title: "Some title" - description: "Some description" - schema: - name: "Some Object" - fields: - title: - type: string - description: - type: string diff --git a/spec/lib/theme_settings_manager/objects_spec.rb b/spec/lib/theme_settings_manager/objects_spec.rb new file mode 100644 index 00000000000..41858cd27f5 --- /dev/null +++ b/spec/lib/theme_settings_manager/objects_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +RSpec.describe ThemeSettingsManager::Objects do + fab!(:theme) + + before { SiteSetting.experimental_objects_type_for_theme_settings = true } + + it "can store a list of objects" do + objects_setting = + described_class.new( + "some_objects_setting", + [{ "title" => "Some title", "description" => "Some description" }], + theme, + schema: { + name: "Some Object", + fields: { + title: { + type: "string", + }, + description: { + type: "string", + }, + }, + }, + ) + + expect(objects_setting.value).to eq( + [{ "title" => "Some title", "description" => "Some description" }], + ) + + objects_setting.value = [{ title: "title 1", description: "description 1" }] + + expect(objects_setting.value).to eq( + [{ "title" => "title 1", "description" => "description 1" }], + ) + end +end diff --git a/spec/lib/theme_settings_manager_spec.rb b/spec/lib/theme_settings_manager_spec.rb index 55b5ca307e4..944c0b59891 100644 --- a/spec/lib/theme_settings_manager_spec.rb +++ b/spec/lib/theme_settings_manager_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "theme_settings_manager" - RSpec.describe ThemeSettingsManager do let!(:theme) { Fabricate(:theme) } @@ -12,8 +10,6 @@ RSpec.describe ThemeSettingsManager do theme.settings end - before { SiteSetting.experimental_objects_type_for_theme_settings = true } - describe "Enum" do it "only accepts values from its choices" do enum_setting = theme_settings[:enum_setting] @@ -186,21 +182,4 @@ RSpec.describe ThemeSettingsManager do end end end - - describe ThemeSettingsManager::Objects do - it "can store a list of objects" do - objects_setting = theme_settings[:valid_objects_setting] - - expect(objects_setting.value).to eq( - [{ "title" => "Some title", "description" => "Some description" }], - ) - - objects_setting.value = [{ title: "title 1", description: "description 1" }] - objects_setting = theme.reload.settings[:valid_objects_setting] - - expect(objects_setting.value).to eq( - [{ "title" => "title 1", "description" => "description 1" }], - ) - end - end end