mirror of
https://github.com/discourse/discourse.git
synced 2024-12-28 12:43:53 +08:00
1eb70973a2
This PR adds a theme modifier and route so that custom themes can opt to show their own homepage. See PR description for example usage.
120 lines
3.2 KiB
Ruby
120 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
class ThemeModifierSet < ActiveRecord::Base
|
|
class ThemeModifierSetError < StandardError
|
|
end
|
|
|
|
belongs_to :theme
|
|
|
|
def self.modifiers
|
|
@modifiers ||= self.load_modifiers
|
|
end
|
|
|
|
validate :type_validator
|
|
|
|
def type_validator
|
|
ThemeModifierSet.modifiers.each do |k, config|
|
|
value = read_attribute(k)
|
|
next if value.nil?
|
|
|
|
case config[:type]
|
|
when :boolean
|
|
next if [true, false].include?(value)
|
|
when :string_array
|
|
next if value.is_a?(Array) && value.all? { |v| v.is_a?(String) }
|
|
end
|
|
errors.add(k, :invalid)
|
|
end
|
|
end
|
|
|
|
after_save do
|
|
SvgSprite.expire_cache if saved_change_to_svg_icons?
|
|
CSP::Extension.clear_theme_extensions_cache! if saved_change_to_csp_extensions?
|
|
end
|
|
|
|
# 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 = self.modifiers[modifier_name])
|
|
|
|
all_values =
|
|
self
|
|
.where(theme_id: theme_ids)
|
|
.where.not(modifier_name => nil)
|
|
.map { |s| s.public_send(modifier_name) }
|
|
case config[:type]
|
|
when :boolean
|
|
all_values.any?
|
|
when :string_array
|
|
all_values.flatten(1)
|
|
else
|
|
raise ThemeModifierSetError "Invalid theme modifier combine_mode"
|
|
end
|
|
end
|
|
|
|
def topic_thumbnail_sizes
|
|
array = read_attribute(:topic_thumbnail_sizes)
|
|
|
|
return if array.nil?
|
|
|
|
array
|
|
.map do |dimension|
|
|
parts = dimension.split("x")
|
|
next if parts.length != 2
|
|
[parts[0].to_i, parts[1].to_i]
|
|
end
|
|
.filter(&:present?)
|
|
end
|
|
|
|
def topic_thumbnail_sizes=(val)
|
|
return write_attribute(:topic_thumbnail_sizes, val) if val.nil?
|
|
return write_attribute(:topic_thumbnail_sizes, val) if !val.is_a?(Array)
|
|
if !val.all? { |v| v.is_a?(Array) && v.length == 2 }
|
|
return write_attribute(:topic_thumbnail_sizes, val)
|
|
end
|
|
|
|
super(val.map { |dim| "#{dim[0]}x#{dim[1]}" })
|
|
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 %w[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
|
|
if !%i[boolean string].include?(info.type)
|
|
raise ThemeModifierSetError "Invalid theme modifier column type"
|
|
end
|
|
end
|
|
|
|
hash[column_name.to_sym] = { type: type }
|
|
end
|
|
hash
|
|
end
|
|
end
|
|
|
|
# == Schema Information
|
|
#
|
|
# Table name: theme_modifier_sets
|
|
#
|
|
# id :bigint not null, primary key
|
|
# theme_id :bigint not null
|
|
# serialize_topic_excerpts :boolean
|
|
# csp_extensions :string is an Array
|
|
# svg_icons :string is an Array
|
|
# topic_thumbnail_sizes :string is an Array
|
|
# custom_homepage :boolean
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_theme_modifier_sets_on_theme_id (theme_id) UNIQUE
|
|
#
|