<commit_before>module SiteSettingExtension

  module Types
    String = 1
    Time = 2
    Fixnum = 3
    Float = 4
    Bool = 5
    Null = 6
  end

  def mutex
    @mutex ||= Mutex.new
  end

  def current
    @@containers ||= {}
    @@containers[RailsMultisite::ConnectionManagement.current_db] ||= {}
  end

  def defaults
    @defaults ||= {}
  end

  def setting(name, default = nil, type = nil)
    mutex.synchronize do
      self.defaults[name] = default
      current_value = current.has_key?(name) ? current[name] : default
      setup_methods(name, current_value)
    end
  end

  # just like a setting, except that it is available in javascript via DiscourseSession
  def client_setting(name, default = nil, type = nil)
    setting(name,default,type)
    @@client_settings ||= []
    @@client_settings << name
  end

  def client_settings
    @@client_settings
  end


  def client_settings_json
    Rails.cache.fetch(SiteSettingExtension.client_settings_cache_key, expires_in: 30.minutes) do
      MultiJson.dump(Hash[*@@client_settings.map{|n| [n, self.send(n)]}.flatten])
    end
  end

  # Retrieve all settings
  def all_settings
    @defaults.map do |s, v|
      {setting: s,
       description: description(s),
       default: v,
       value: send(s).to_s}
    end
  end

  def description(setting)
    I18n.t("site_settings.#{setting}")
  end

  # table is not in the db yet, initial migration, etc
  def table_exists?
    @table_exists = ActiveRecord::Base.connection.table_exists? 'site_settings' if @table_exists == nil
    @table_exists
  end

  def self.client_settings_cache_key
    "client_settings_json"
  end

  # refresh all the site settings
  def refresh!
    return unless table_exists?
    mutex.synchronize do
      ensure_listen_for_changes
      old = current
      changes = []
      deletions = []

      all_settings = SiteSetting.select([:name,:value,:data_type])
      new_hash =  Hash[*(all_settings.map{|s| [s.name.intern, convert(s.value,s.data_type)]}.to_a.flatten)]

      # add defaults
      new_hash = defaults.merge(new_hash)

      new_hash.each do |name, value|
        changes << [name,value] if !old.has_key?(name) || old[name] != value
      end

      old.each do |name,value|
        deletions << [name,value] unless new_hash.has_key?(name)
      end

      if deletions.length > 0 || changes.length > 0
        @current = new_hash
        changes.each do |name, val|
          setup_methods name, val
        end
        deletions.each do |name,val|
          setup_methods name, defaults[name]
        end
      end

      Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
    end
  end

  def ensure_listen_for_changes
    unless @subscribed
      pid = process_id
      MessageBus.subscribe("/site_settings") do |msg|
        message = msg.data
        if message["process"] != pid
          begin
            # picks a db
            MessageBus.on_connect.call(msg.site_id)
            SiteSetting.refresh!
          ensure
            MessageBus.on_disconnect.call(msg.site_id)
          end
        end
      end
      @subscribed = true
    end
  end

  def process_id
    @@process_id ||= SecureRandom.uuid
  end

  def remove_override!(name)
    return unless table_exists?
    SiteSetting.where(:name => name).destroy_all
  end

  def add_override!(name,val)
    return unless table_exists?

    setting = SiteSetting.where(:name => name).first
    type = get_data_type(defaults[name])

    if type == Types::Bool && val != true && val != false
      val = (val == "t" || val == "true")
    end

    if type == Types::Fixnum && !(Fixnum === val)
      val = val.to_i
    end

    if setting
      setting.value = val
      setting.data_type = type
      setting.save
    else
      SiteSetting.create!(:name => name, :value => val, :data_type => type)
    end

    MessageBus.publish('/site_settings', {process: process_id})
  end


  protected
<commit_msg>Quick fix for Boolean SiteSettings <commit_after>module SiteSettingExtension

  module Types
    String = 1
    Time = 2
    Fixnum = 3
    Float = 4
    Bool = 5
    Null = 6
  end

  def mutex
    @mutex ||= Mutex.new
  end

  def current
    @@containers ||= {}
    @@containers[RailsMultisite::ConnectionManagement.current_db] ||= {}
  end

  def defaults
    @defaults ||= {}
  end

  def setting(name, default = nil, type = nil)
    mutex.synchronize do
      self.defaults[name] = default
      current_value = current.has_key?(name) ? current[name] : default
      setup_methods(name, current_value)
    end
  end

  # just like a setting, except that it is available in javascript via DiscourseSession
  def client_setting(name, default = nil, type = nil)
    setting(name,default,type)
    @@client_settings ||= []
    @@client_settings << name
  end

  def client_settings
    @@client_settings
  end


  def client_settings_json
    Rails.cache.fetch(SiteSettingExtension.client_settings_cache_key, expires_in: 30.minutes) do
      MultiJson.dump(Hash[*@@client_settings.map{|n| [n, self.send(n)]}.flatten])
    end
  end

  # Retrieve all settings
  def all_settings
    @defaults.map do |s, v|
      {setting: s,
       description: description(s),
       default: v,
       value: send(s).to_s}
    end
  end

  def description(setting)
    I18n.t("site_settings.#{setting}")
  end

  # table is not in the db yet, initial migration, etc
  def table_exists?
    @table_exists = ActiveRecord::Base.connection.table_exists? 'site_settings' if @table_exists == nil
    @table_exists
  end

  def self.client_settings_cache_key
    "client_settings_json"
  end

  # refresh all the site settings
  def refresh!
    return unless table_exists?
    mutex.synchronize do
      ensure_listen_for_changes
      old = current
      changes = []
      deletions = []

      all_settings = SiteSetting.select([:name,:value,:data_type])
      new_hash =  Hash[*(all_settings.map{|s| [s.name.intern, convert(s.value,s.data_type)]}.to_a.flatten)]

      # add defaults
      new_hash = defaults.merge(new_hash)

      new_hash.each do |name, value|
        changes << [name,value] if !old.has_key?(name) || old[name] != value
      end

      old.each do |name,value|
        deletions << [name,value] unless new_hash.has_key?(name)
      end

      if deletions.length > 0 || changes.length > 0
        @current = new_hash
        changes.each do |name, val|
          setup_methods name, val
        end
        deletions.each do |name,val|
          setup_methods name, defaults[name]
        end
      end

      Rails.cache.delete(SiteSettingExtension.client_settings_cache_key)
    end
  end

  def ensure_listen_for_changes
    unless @subscribed
      pid = process_id
      MessageBus.subscribe("/site_settings") do |msg|
        message = msg.data
        if message["process"] != pid
          begin
            # picks a db
            MessageBus.on_connect.call(msg.site_id)
            SiteSetting.refresh!
          ensure
            MessageBus.on_disconnect.call(msg.site_id)
          end
        end
      end
      @subscribed = true
    end
  end

  def process_id
    @@process_id ||= SecureRandom.uuid
  end

  def remove_override!(name)
    return unless table_exists?
    SiteSetting.where(:name => name).destroy_all
  end

  def add_override!(name,val)
    return unless table_exists?

    setting = SiteSetting.where(:name => name).first
    type = get_data_type(defaults[name])

    if type == Types::Bool && val != true && val != false
      val = (val == "t" || val == "true") ? 't' : 'f'
    end

    if type == Types::Fixnum && !(Fixnum === val)
      val = val.to_i
    end

    if setting
      setting.value = val
      setting.data_type = type
      setting.save
    else
      SiteSetting.create!(:name => name, :value => val, :data_type => type)
    end

    MessageBus.publish('/site_settings', {process: process_id})
  end


  protected

{'fraction_non_alphanumeric': 0.10454545454545454, 'fraction_numerical': 0.0030303030303030303, 'mean_word_length': 2.587409420289855, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4985284', 'n_tokens_mistral': 2560, 'n_tokens_neox': 2455, 'n_words': 607}