DEV: improve design of site setting default provider

This refactors it so "Defaults provider" is only responsible for "defaults"

Locale handling and management of locale settings is moved back into
SiteSettingExtension

This eliminates complex state management using DistributedCache and makes
it way easier to test SiteSettingExtension
This commit is contained in:
Sam
2018-06-01 12:22:47 +10:00
parent d2880246cd
commit f331d2603d
7 changed files with 122 additions and 260 deletions

View File

@@ -1,31 +1,23 @@
# frozen_string_literal: true
module SiteSettings; end
# A cache for providing default value based on site locale
class SiteSettings::DefaultsProvider
include Enumerable
CONSUMED_OPTS = %i[default locale_default].freeze
DEFAULT_LOCALE_KEY = :default_locale
DEFAULT_LOCALE = 'en'.freeze
DEFAULT_CATEGORY = 'required'.freeze
@@site_locales ||= DistributedCache.new('site_locales')
DEFAULT_LOCALE = 'en'
def initialize(site_setting)
@site_setting = site_setting
@site_setting.refresh_settings << DEFAULT_LOCALE_KEY
@defaults = {}
@defaults[DEFAULT_LOCALE.to_sym] = {}
refresh_site_locale!
end
def load_setting(name_arg, value, opts = {})
def load_setting(name_arg, value, locale_defaults)
name = name_arg.to_sym
@defaults[DEFAULT_LOCALE.to_sym][name] = value
if (locale_default = opts[:locale_default])
locale_default.each do |locale, v|
if (locale_defaults)
locale_defaults.each do |locale, v|
locale = locale.to_sym
@defaults[locale] ||= {}
@defaults[locale][name] = v
@@ -34,15 +26,19 @@ class SiteSettings::DefaultsProvider
end
def db_all
@site_setting.provider.all.delete_if { |s| s.name.to_sym == DEFAULT_LOCALE_KEY }
@site_setting.provider.all
end
def all
@defaults[DEFAULT_LOCALE.to_sym].merge(@defaults[self.site_locale.to_sym] || {})
def all(locale = nil)
if locale
@defaults[DEFAULT_LOCALE.to_sym].merge(@defaults[locale.to_sym] || {})
else
@defaults[DEFAULT_LOCALE.to_sym].dup
end
end
def get(name)
@defaults.dig(self.site_locale.to_sym, name.to_sym) ||
def get(name, locale = DEFAULT_LOCALE)
@defaults.dig(locale.to_sym, name.to_sym) ||
@defaults.dig(DEFAULT_LOCALE.to_sym, name.to_sym)
end
alias [] get
@@ -50,81 +46,25 @@ class SiteSettings::DefaultsProvider
# Used to override site settings in dev/test env
def set_regardless_of_locale(name, value)
name = name.to_sym
if @site_setting.has_setting?(name)
if name == :default_locale || @site_setting.has_setting?(name)
@defaults.each { |_, hash| hash.delete(name) }
@defaults[DEFAULT_LOCALE.to_sym][name] = value
value, type = @site_setting.type_supervisor.to_db_value(name, value)
@defaults[self.site_locale.to_sym] ||= {}
@defaults[self.site_locale.to_sym][name] = @site_setting.type_supervisor.to_rb_value(name, value, type)
@defaults[SiteSetting.default_locale.to_sym] ||= {}
@defaults[SiteSetting.default_locale.to_sym][name] = @site_setting.type_supervisor.to_rb_value(name, value, type)
else
raise ArgumentError.new("No setting named '#{name}' exists")
end
end
def site_locale
@@site_locales[current_db]
end
def site_locale=(val)
val = val.to_s
raise Discourse::InvalidParameters.new(:value) unless LocaleSiteSetting.valid_value?(val)
if val != @@site_locales[current_db]
@site_setting.provider.save(DEFAULT_LOCALE_KEY, val, SiteSetting.types[:string])
refresh_site_locale!
@site_setting.refresh!
Discourse.request_refresh!
end
@@site_locales[current_db]
end
def each(&block)
self.all.each do |key, value|
block.call(key.to_sym, value)
end
end
def locale_setting_hash
{
setting: DEFAULT_LOCALE_KEY,
default: DEFAULT_LOCALE,
category: DEFAULT_CATEGORY,
description: @site_setting.description(DEFAULT_LOCALE_KEY),
type: SiteSetting.types[SiteSetting.types[:enum]],
preview: nil,
value: @@site_locales[current_db],
valid_values: LocaleSiteSetting.values,
translate_names: LocaleSiteSetting.translate_names?
}
end
def refresh_site_locale!
RailsMultisite::ConnectionManagement.each_connection do |db|
@@site_locales[db] =
if GlobalSetting.respond_to?(DEFAULT_LOCALE_KEY) &&
(global_val = GlobalSetting.send(DEFAULT_LOCALE_KEY)) &&
!global_val.blank?
global_val
elsif (db_val = @site_setting.provider.find(DEFAULT_LOCALE_KEY))
db_val.value.to_s
else
DEFAULT_LOCALE
end
@@site_locales[db]
end
end
def has_setting?(name)
has_key?(name.to_sym) || has_key?("#{name.to_s}?".to_sym)
has_key?(name.to_sym) || has_key?("#{name.to_s}?".to_sym) || name.to_sym == :default_locale
end
private
def has_key?(name)
@defaults[self.site_locale.to_sym]&.key?(name) ||
@defaults[DEFAULT_LOCALE.to_sym].key?(name) || name == DEFAULT_LOCALE_KEY
@defaults[DEFAULT_LOCALE.to_sym].key?(name)
end
def current_db