[#778] Properly cache Liquid markup
This commit moves the markup caching into Liquid rendering. As Liquid allows to return different results depending on the environment (variables, logged user, ...) we only cache the page if it contains no active content. Unfortunetely, active content currently also includes the TOC in wiki pages.
This commit is contained in:
parent
637ca24aed
commit
e91a1e010f
|
@ -19,15 +19,19 @@ module ChiliProject
|
|||
def self.included(base)
|
||||
base.send(:include, InstanceMethods)
|
||||
base.class_eval do
|
||||
alias_method_chain :render_all, :cleaned_whitespace
|
||||
alias_method_chain :render_all, :cleaned_whitespace_and_cache
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def render_all_with_cleaned_whitespace(list, context)
|
||||
def render_all_with_cleaned_whitespace_and_cache(list, context)
|
||||
# Remove the leading newline in a block's content
|
||||
list[0].sub!(/\A\r?\n/, "") if list[0].is_a?(String)
|
||||
render_all_without_cleaned_whitespace(list, context)
|
||||
|
||||
# prevent caching if there are any potentially active elements
|
||||
context.not_cachable! if list.any? { |token| token.respond_to?(:render) }
|
||||
|
||||
render_all_without_cleaned_whitespace_and_cache(list, context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,6 +47,14 @@ module ChiliProject
|
|||
def html_results
|
||||
registers[:html_results] ||= {}
|
||||
end
|
||||
|
||||
def cacheable?
|
||||
registers.has_key?(:cachable) ? !!registers[:cachable] : true
|
||||
end
|
||||
|
||||
def not_cachable!
|
||||
registers[:cachable] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -74,6 +74,26 @@ module ChiliProject
|
|||
context = context_from_render_options(*args)
|
||||
context.registers[:html_results] ||= {}
|
||||
|
||||
obj = context.registers[:object]
|
||||
attribute = context.registers[:attribute]
|
||||
|
||||
if Setting.cache_formatted_text? && cache_key = cache_key_for(Setting.text_formatting, obj, attribute)
|
||||
# Text retrieved from the cache store may be frozen
|
||||
# We need to dup it so we can do in-place substitutions with gsub!
|
||||
result = Rails.cache.fetch(cache_key)
|
||||
result ||= begin
|
||||
result = render_context(context)
|
||||
Rails.cache.write(cache_key, result) if context.cacheable?
|
||||
result
|
||||
end.dup
|
||||
else
|
||||
render_context(context)
|
||||
end
|
||||
end
|
||||
|
||||
def render_context(context)
|
||||
return '' if @root.nil?
|
||||
|
||||
# ENTER THE RENDERING STAGE
|
||||
|
||||
# 1. Render the input as Liquid
|
||||
|
@ -88,8 +108,8 @@ module ChiliProject
|
|||
|
||||
# 2. Perform the Wiki markup transformation (e.g. Textile)
|
||||
obj = context.registers[:object]
|
||||
attr = context.registers[:attribute]
|
||||
result = Redmine::WikiFormatting.to_html(Setting.text_formatting, result, :object => obj, :attribute => attr)
|
||||
attribute = context.registers[:attribute]
|
||||
result = Redmine::WikiFormatting.to_html(Setting.text_formatting, result, :object => obj, :attribute => attribute)
|
||||
|
||||
# 3. Now finally, replace the captured raw HTML bits in the final content
|
||||
length = nil
|
||||
|
@ -105,6 +125,13 @@ module ChiliProject
|
|||
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
def cache_key_for(format, object, attribute)
|
||||
if object && attribute && !object.new_record? && object.respond_to?(:updated_on) && !format.blank?
|
||||
"formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{object.updated_on.to_s(:number)}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,27 +41,7 @@ module Redmine
|
|||
end
|
||||
|
||||
def to_html(format, text, options = {}, &block)
|
||||
if Setting.cache_formatted_text? && text.size > 2.kilobyte && cache_store && cache_key = cache_key_for(format, options[:object], options[:attribute])
|
||||
# Text retrieved from the cache store may be frozen
|
||||
# We need to dup it so we can do in-place substitutions with gsub!
|
||||
cache_store.fetch cache_key do
|
||||
formatter_for(format).new(text).to_html
|
||||
end.dup
|
||||
else
|
||||
formatter_for(format).new(text).to_html
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a cache key for the given text +format+, +object+ and +attribute+ or nil if no caching should be done
|
||||
def cache_key_for(format, object, attribute)
|
||||
if object && attribute && !object.new_record? && object.respond_to?(:updated_on) && !format.blank?
|
||||
"formatted_text/#{format}/#{object.class.model_name.cache_key}/#{object.id}-#{attribute}-#{object.updated_on.to_s(:number)}"
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the cache store used to cache HTML output
|
||||
def cache_store
|
||||
ActionController::Base.cache_store
|
||||
formatter_for(format).new(text).to_html
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue