From ec2d49d48a9576a9d07f2c99b49bf3f6b79cd32f Mon Sep 17 00:00:00 2001 From: David Taylor Date: Thu, 12 Mar 2020 16:35:28 +0000 Subject: [PATCH] DEV: Allow plugins to add theme modifiers via db migrations (#9192) --- app/models/remote_theme.rb | 2 +- app/models/theme.rb | 2 +- app/models/theme_modifier_set.rb | 41 +++++++++++++++++++------- lib/theme_modifier_helper.rb | 2 +- spec/models/theme_modifier_set_spec.rb | 6 ++++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/app/models/remote_theme.rb b/app/models/remote_theme.rb index 6afa44c2a16..e95fe25c517 100644 --- a/app/models/remote_theme.rb +++ b/app/models/remote_theme.rb @@ -145,7 +145,7 @@ class RemoteTheme < ActiveRecord::Base raise ImportError, I18n.t("themes.import_error.about_json_values", errors: self.errors.full_messages.join(",")) end - ThemeModifierSet::MODIFIERS.keys.each do |modifier_name| + ThemeModifierSet.modifiers.keys.each do |modifier_name| theme.theme_modifier_set.public_send(:"#{modifier_name}=", theme_info.dig("modifiers", modifier_name.to_s)) end if !theme.theme_modifier_set.valid? diff --git a/app/models/theme.rb b/app/models/theme.rb index 35fd6630925..c20e04d9053 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -538,7 +538,7 @@ class Theme < ActiveRecord::Base end meta[:modifiers] = {}.tap do |hash| - ThemeModifierSet::MODIFIERS.keys.each do |modifier| + ThemeModifierSet.modifiers.keys.each do |modifier| value = self.theme_modifier_set.public_send(modifier) hash[modifier] = value if !value.nil? end diff --git a/app/models/theme_modifier_set.rb b/app/models/theme_modifier_set.rb index 262b0638ae0..99a8818f58c 100644 --- a/app/models/theme_modifier_set.rb +++ b/app/models/theme_modifier_set.rb @@ -4,16 +4,14 @@ class ThemeModifierSet < ActiveRecord::Base belongs_to :theme - MODIFIERS ||= { - serialize_topic_excerpts: { combine_mode: :any, type: :boolean }, - csp_extensions: { combine_mode: :flatten, type: :string_array }, - svg_icons: { combine_mode: :flatten, type: :string_array }, - } + def self.modifiers + @modifiers ||= self.load_modifiers + end validate :type_validator def type_validator - MODIFIERS.each do |k, config| + ThemeModifierSet.modifiers.each do |k, config| value = public_send(k) next if value.nil? @@ -39,18 +37,41 @@ class ThemeModifierSet < ActiveRecord::Base # Given the ids of multiple active themes / theme components, this function # will combine them into a 'resolved' behavior def self.resolve_modifier_for_themes(theme_ids, modifier_name) - return nil if !(config = MODIFIERS[modifier_name]) + return nil if !(config = self.modifiers[modifier_name]) all_values = self.where(theme_id: theme_ids).where.not(modifier_name => nil).pluck(modifier_name) - case config[:combine_mode] - when :any + case config[:type] + when :boolean all_values.any? - when :flatten + when :string_array all_values.flatten(1) else raise ThemeModifierSetError "Invalid theme modifier combine_mode" end end + + private + + # Build the list of modifiers from the DB schema. + # This allows plugins to introduce new modifiers by adding columns to the table + def self.load_modifiers + hash = {} + columns_hash.each do |column_name, info| + next if ["id", "theme_id"].include?(column_name) + + type = nil + if info.type == :string && info.array? + type = :string_array + elsif info.type == :boolean && !info.array? + type = :boolean + else + raise ThemeModifierSetError "Invalid theme modifier column type" if ![:boolean, :string].include?(info.type) + end + + hash[column_name.to_sym] = { type: type } + end + hash + end end # == Schema Information diff --git a/lib/theme_modifier_helper.rb b/lib/theme_modifier_helper.rb index 3d72a6d35aa..74f49b322a1 100644 --- a/lib/theme_modifier_helper.rb +++ b/lib/theme_modifier_helper.rb @@ -4,7 +4,7 @@ class ThemeModifierHelper @theme_ids = theme_ids || request&.env&.[](:resolved_theme_ids) end - ThemeModifierSet::MODIFIERS.keys.each do |modifier| + ThemeModifierSet.modifiers.keys.each do |modifier| define_method(modifier) do Theme.lookup_modifier(@theme_ids, modifier) end diff --git a/spec/models/theme_modifier_set_spec.rb b/spec/models/theme_modifier_set_spec.rb index ca770f339fb..9e7cbf0e021 100644 --- a/spec/models/theme_modifier_set_spec.rb +++ b/spec/models/theme_modifier_set_spec.rb @@ -20,5 +20,11 @@ describe ThemeModifierSet do expect(ThemeModifierSet.resolve_modifier_for_themes([t1.id, t2.id], :serialize_topic_excerpts)).to eq(false) end + + it "builds modifiers list from database" do + expect(ThemeModifierSet.modifiers.keys).to include(:serialize_topic_excerpts, :csp_extensions) + expect(ThemeModifierSet.modifiers[:serialize_topic_excerpts][:type]).to eq(:boolean) + expect(ThemeModifierSet.modifiers[:csp_extensions][:type]).to eq(:string_array) + end end end