summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorAlexander Tsvyashchenko <ndl@ndl.kiev.ua>2010-01-11 12:38:44 (GMT)
committerAlexander Tsvyashchenko <ndl@ndl.kiev.ua>2010-01-11 12:38:44 (GMT)
commite085eb821ca7c9e74bc0f2688cb6b7ae06b6bf80 (patch)
treef71428e57a5996e6e4164dfdb09ceb3d7f0edaa1 /app
downloadwiki_external_filter-e085eb821ca7c9e74bc0f2688cb6b7ae06b6bf80.zip
wiki_external_filter-e085eb821ca7c9e74bc0f2688cb6b7ae06b6bf80.tar.gz
wiki_external_filter-e085eb821ca7c9e74bc0f2688cb6b7ae06b6bf80.tar.bz2
- Initial commit.
Diffstat (limited to 'app')
-rw-r--r--app/controllers/wiki_external_filter_controller.rb19
-rw-r--r--app/helpers/wiki_external_filter_helper.rb120
-rw-r--r--app/views/wiki_external_filter/_settings.html.erb21
-rw-r--r--app/views/wiki_external_filter/macro_block.html.erb29
-rw-r--r--app/views/wiki_external_filter/macro_inline.html.erb25
5 files changed, 214 insertions, 0 deletions
diff --git a/app/controllers/wiki_external_filter_controller.rb b/app/controllers/wiki_external_filter_controller.rb
new file mode 100644
index 0000000..23c03dc
--- /dev/null
+++ b/app/controllers/wiki_external_filter_controller.rb
@@ -0,0 +1,19 @@
+
+class WikiExternalFilterController < ApplicationController
+
+ include WikiExternalFilterHelper
+
+ def filter
+ name = params[:name]
+ macro = params[:macro]
+ config = load_config
+ cache_key = self.construct_cache_key(macro, name)
+ content = read_fragment cache_key
+
+ if (content)
+ send_data content, :type => config[macro]['content_type'], :disposition => 'inline'
+ else
+ render_404
+ end
+ end
+end
diff --git a/app/helpers/wiki_external_filter_helper.rb b/app/helpers/wiki_external_filter_helper.rb
new file mode 100644
index 0000000..931b77a
--- /dev/null
+++ b/app/helpers/wiki_external_filter_helper.rb
@@ -0,0 +1,120 @@
+require 'digest/sha2'
+
+module WikiExternalFilterHelper
+
+ def load_config
+ unless @config
+ config_file = "#{RAILS_ROOT}/config/wiki_external_filter.yml"
+ unless File.exists?(config_file)
+ raise "Config not found: #{config_file}"
+ end
+ @config = YAML.load_file(config_file)[RAILS_ENV]
+ end
+ @config
+ end
+
+ def has_macro(macro)
+ config = load_config
+ config.key?(macro)
+ end
+
+ module_function :load_config, :has_macro
+
+ def construct_cache_key(macro, name)
+ ['wiki_external_filter', macro, name].join("/")
+ end
+
+ def build(text, macro, info)
+
+ name = Digest::SHA256.hexdigest(text)
+ result = {}
+ content = nil
+ cache_key = nil
+ expires = 0
+
+ if info.key?('cache_seconds')
+ expires = info['cache_seconds']
+ else
+ expires = Setting.plugin_wiki_external_filter['cache_seconds'].to_i
+ end
+
+ if expires > 0
+ cache_key = self.construct_cache_key(macro, name)
+ content = read_fragment cache_key, :expires_in => expires.seconds
+ end
+
+ if content
+ result[:source] = text
+ result[:content] = content
+ result[:content_type] = info['content_type']
+ RAILS_DEFAULT_LOGGER.debug "from cache: #{name}"
+ else
+ result = self.build_forced(text, info)
+ if result[:status]
+ if expires > 0
+ write_fragment cache_key, result[:content], :expires_in => expires.seconds
+ RAILS_DEFAULT_LOGGER.debug "cache saved: #{name}"
+ end
+ else
+ raise "Error applying external filter: #{result[:content]}"
+ end
+ end
+
+ result[:name] = name
+ result[:macro] = macro
+
+ return result
+ end
+
+ def build_forced(text, info)
+
+ result = {}
+
+ RAILS_DEFAULT_LOGGER.debug "executing command: #{info['command']}"
+
+ content = IO.popen(info['command'], 'r+b') { |f|
+ f.write info[:prolog] if info.key?(:prolog)
+ f.write CGI.unescapeHTML(text)
+ f.write info[:epilog] if info.key?(:epilog)
+ f.close_write
+ f.read
+ }
+
+ RAILS_DEFAULT_LOGGER.info("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}")
+
+ result[:content] = content
+ result[:content_type] = info['content_type']
+ result[:source] = text
+ result[:status] = $?.exitstatus == 0
+
+ return result
+ end
+
+ def render_tag(result)
+ render_to_string :template => 'wiki_external_filter/macro_inline', :layout => false, :locals => result
+ end
+
+ def render_block(result, wiki_name)
+ result = result.dup
+ result[:wiki_name] = wiki_name
+ render_to_string :template => 'wiki_external_filter/macro_block', :layout => false, :locals => result
+ end
+
+ class Macro
+ def initialize(view, source, macro, info)
+ @view = view
+ @view.controller.extend(WikiExternalFilterHelper)
+ source.gsub!(/<br \/>/, "")
+ source.gsub!(/<\/?p>/, "")
+ @result = @view.controller.build(source, macro, info)
+ end
+
+ def render()
+ @view.controller.render_tag(@result)
+ end
+
+ def render_block(wiki_name)
+ @view.controller.render_block(@result, wiki_name)
+ end
+ end
+end
diff --git a/app/views/wiki_external_filter/_settings.html.erb b/app/views/wiki_external_filter/_settings.html.erb
new file mode 100644
index 0000000..3ba45d2
--- /dev/null
+++ b/app/views/wiki_external_filter/_settings.html.erb
@@ -0,0 +1,21 @@
+<fieldset>
+ <legend>Caching Settings</legend>
+ <p>
+ <label>Cache expiration time</label><%= text_field_tag 'settings[cache_seconds]', @settings['cache_seconds'] %> seconds
+ </p>
+ <p>
+ Enter zero to disable caching. Make sure to configure fragment_cache_store if you use the value &gt; 0.
+ </p>
+ <p>
+ Configuration example for ActiveSupport::Cache::FileStore, config/environments/production.rb file:<br/>
+ <br/>
+ ...<br/>
+ config.action_controller.fragment_cache_store = :file_store, &quot;#{RAILS_ROOT}/cache&quot;<br/>
+ ...
+ </p>
+ <p>
+ Current cache settings are:<br/>
+ ActionController::Base.cache_configured? = <%= h ActionController::Base.cache_configured? ? "true" : "false" %><br/>
+ ActionController::Base.fragment_cache_store = <%= h ActionController::Base.fragment_cache_store.inspect %>
+ </p>
+</fieldset>
diff --git a/app/views/wiki_external_filter/macro_block.html.erb b/app/views/wiki_external_filter/macro_block.html.erb
new file mode 100644
index 0000000..a72ab02
--- /dev/null
+++ b/app/views/wiki_external_filter/macro_block.html.erb
@@ -0,0 +1,29 @@
+<div class='externalfilterblock'>
+<%
+ case content_type
+ when /image\// then
+%>
+ <img src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' alt="<%= h source %>" />
+<%
+ when /text\/plain/ then
+%>
+ <pre><%= h content %></pre>
+<%
+ when /\/.*(x|ht)ml/ then
+%>
+ <div><%= content %></div>
+<%
+ else
+%>
+ <object class='externalfilterinline' name='<%= name %>' data='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>">
+ <embed name='<%= name %>-2' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>" />
+ </object>
+<%
+ end
+%>
+ <br/>
+ <span class='wiki_page'>Goto source: [[<%= wiki_name %>]]</span>
+</div>
+<% content_for :header_tags do %>
+ <%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
+<% end %>
diff --git a/app/views/wiki_external_filter/macro_inline.html.erb b/app/views/wiki_external_filter/macro_inline.html.erb
new file mode 100644
index 0000000..32d1264
--- /dev/null
+++ b/app/views/wiki_external_filter/macro_inline.html.erb
@@ -0,0 +1,25 @@
+<%
+ case content_type
+ when /image\// then
+%>
+ <img class='externalfilterinline' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' alt="<%= h source %>" />
+<%
+ when /text\/plain/ then
+%>
+ <pre class='externalfilterinline'><%= h content %></pre>
+<%
+ when /\/.*(x|ht)ml/ then
+%>
+ <div class='externalfilterinline'><%= content %></div>
+<%
+ else
+%>
+ <object class='externalfilterinline' name='<%= name %>' data='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>">
+ <embed name='<%= name %>-2' src='<%= url_for(:controller => 'wiki_external_filter', :action => 'filter', :macro => macro, :name => name) %>' type='<%= content_type %>' title="<%= h source %>" />
+ </object>
+<%
+ end
+%>
+<% content_for :header_tags do %>
+ <%= stylesheet_link_tag "wiki_external_filter.css", :plugin => "wiki_external_filter", :media => :all %>
+<% end %>