mirror of
https://github.com/discourse/discourse.git
synced 2025-05-28 22:57:40 +08:00
Initial release of Discourse
This commit is contained in:
144
app/models/site_customization.rb
Normal file
144
app/models/site_customization.rb
Normal file
@ -0,0 +1,144 @@
|
||||
class SiteCustomization < ActiveRecord::Base
|
||||
|
||||
CACHE_PATH = 'stylesheet-cache'
|
||||
@lock = Mutex.new
|
||||
|
||||
before_create do
|
||||
self.position ||= (SiteCustomization.maximum(:position) || 0) + 1
|
||||
self.enabled ||= false
|
||||
self.key ||= SecureRandom.uuid
|
||||
true
|
||||
end
|
||||
|
||||
before_save do
|
||||
if self.stylesheet_changed?
|
||||
begin
|
||||
self.stylesheet_baked = Sass.compile self.stylesheet
|
||||
rescue Sass::SyntaxError => e
|
||||
error = e.sass_backtrace_str("custom stylesheet")
|
||||
error.gsub!("\n", '\A ')
|
||||
error.gsub!("'", '\27 ')
|
||||
|
||||
self.stylesheet_baked =
|
||||
"#main {display: none;}
|
||||
footer {white-space: pre; margin-left: 100px;}
|
||||
footer:after{ content: '#{error}' }"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after_save do
|
||||
if self.stylesheet_changed?
|
||||
if File.exists?(self.stylesheet_fullpath)
|
||||
File.delete self.stylesheet_fullpath
|
||||
end
|
||||
end
|
||||
self.remove_from_cache!
|
||||
if self.stylesheet_changed?
|
||||
self.ensure_stylesheet_on_disk!
|
||||
MessageBus.publish "/file-change/#{self.key}", self.stylesheet_hash
|
||||
end
|
||||
MessageBus.publish "/header-change/#{self.key}", self.header if self.header_changed?
|
||||
|
||||
end
|
||||
|
||||
after_destroy do
|
||||
if File.exists?(self.stylesheet_fullpath)
|
||||
File.delete self.stylesheet_fullpath
|
||||
end
|
||||
self.remove_from_cache!
|
||||
end
|
||||
|
||||
|
||||
def self.custom_stylesheet(preview_style)
|
||||
style = lookup_style(preview_style)
|
||||
style.stylesheet_link_tag.html_safe if style
|
||||
end
|
||||
|
||||
def self.custom_header(preview_style)
|
||||
style = lookup_style(preview_style)
|
||||
style.header.html_safe if style
|
||||
end
|
||||
|
||||
def self.override_default_style(preview_style)
|
||||
style = lookup_style(preview_style)
|
||||
style.override_default_style if style
|
||||
end
|
||||
|
||||
def self.lookup_style(key)
|
||||
|
||||
return if key.blank?
|
||||
|
||||
# cache is cross site resiliant cause key is secure random
|
||||
@cache ||= {}
|
||||
ensure_cache_listener
|
||||
style = @cache[key]
|
||||
return style if style
|
||||
|
||||
@lock.synchronize do
|
||||
style = self.where(key: key).first
|
||||
@cache[key] = style
|
||||
end
|
||||
end
|
||||
|
||||
def self.ensure_cache_listener
|
||||
unless @subscribed
|
||||
klass = self
|
||||
MessageBus.subscribe("/site_customization") do |msg|
|
||||
message = msg.data
|
||||
klass.remove_from_cache!(message["key"], false)
|
||||
end
|
||||
|
||||
@subscribed = true
|
||||
end
|
||||
end
|
||||
|
||||
def self.remove_from_cache!(key, broadcast=true)
|
||||
MessageBus.publish('/site_customization', {key: key}) if broadcast
|
||||
if @cache
|
||||
@lock.synchronize do
|
||||
@cache[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def remove_from_cache!
|
||||
self.class.remove_from_cache!(self.key)
|
||||
end
|
||||
|
||||
def stylesheet_hash
|
||||
Digest::MD5.hexdigest(self.stylesheet)
|
||||
end
|
||||
|
||||
def ensure_stylesheet_on_disk!
|
||||
path = stylesheet_fullpath
|
||||
dir = "#{Rails.root}/public/#{CACHE_PATH}"
|
||||
FileUtils.mkdir_p(dir)
|
||||
unless File.exists?(path)
|
||||
File.open(path, "w") do |f|
|
||||
f.puts self.stylesheet_baked
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def stylesheet_filename
|
||||
file = ""
|
||||
dir = "#{Rails.root}/public/#{CACHE_PATH}"
|
||||
path = dir + file
|
||||
|
||||
"/#{CACHE_PATH}/#{self.key}.css"
|
||||
end
|
||||
|
||||
def stylesheet_fullpath
|
||||
"#{Rails.root}/public#{self.stylesheet_filename}"
|
||||
end
|
||||
|
||||
def stylesheet_link_tag
|
||||
return "" unless self.stylesheet.present?
|
||||
return @stylesheet_link_tag if @stylesheet_link_tag
|
||||
ensure_stylesheet_on_disk!
|
||||
@stylesheet_link_tag = "<link class=\"custom-css\" rel=\"stylesheet\" href=\"#{self.stylesheet_filename}?#{self.stylesheet_hash}\" type=\"text/css\" media=\"screen\">"
|
||||
end
|
||||
|
||||
|
||||
end
|
Reference in New Issue
Block a user