diff --git a/README.markdown b/README.markdown index a897cb2..a1fb03b 100644 --- a/README.markdown +++ b/README.markdown @@ -20,38 +20,33 @@ ones is typically as easy as adding several lines in plugin config file. Installation ============ +** NOTE works only on Redmine > v2.0 ** + 1. It's recommended (but not required) to install [popen4](http://popen4.rubyforge.org/) library first as without it plugin is unable to capture stderr output of external command, so it might be hard to debug it if things go wrong. -2. Get sources from [github](http://github.com/ndl/wiki_external_filter). +2. Get sources from [github](http://github.com/mkinski/wiki_external_filter). 3. See [Installing a plugin](http://www.redmine.org/wiki/redmine/Plugins) on Redmine site. -4. Copy wiki_external_filter.yml from config folder of plugin - directory to the config folder of your redmine installation. 5. After installation it's **strongly recommended** to go to plugin settings and - configure caching: Administration -> Plugins -> Wiki External Filter Plugin: Configure and follow instructions. Note that RoR file-based caching suggested by default does - not implement proper cache expiration: you should either setup a cron task to - clean cache or do it manually from time to time. + configure caching: Administration -> Plugins -> Wiki External Filter Plugin: Configure and follow instructions. 6. To successfully use macros with argument expressions, it's necessary to patch wiki formatting routine so that it preserves macros arguments. - **Redmine 1.0.2:** apply [this patch](http://www.ndl.kiev.ua/downloads/redmine-1.0.2-macros-escaping.patch) to the Redmine core and go to step 7, there's no need to patch individual wiki formatters anymore. + Graphviz will not work until modification MACRO_RE see ungoing [Issue 3061](http://www.redmine.org/issues/3061) + under app/helper/application_helper.rb + MACROS_RE = / + (!)? # escaping + ( + \{\{ # opening tag + ([\w]+) # macro name + (\((.*)\))? # optional arguments + \}\} # closing tag + ) + / - **Redmine 0.9.x:** if you use Markdown Extra, switch to the following fork of [redmine_markdown_extra_formatter](http://github.com/ndl/redmine_markdown_extra_formatter) that contains all necessary changes. [This patch](http://www.ndl.kiev.ua/downloads/redmine_markdown_extra_formatter_fixes.patch.gz) is for older Markdown Extra formatter version and should not be used for new installations. - - **Note**: if you install Markdown Extra formatter - you should enable it in Administration -> Settings -> General -> Text formatting. - - If you use wiki formatter other than Markdown Extra (including default Textile formatter) **you will have to change your wiki formatter yourselves** as follows: - * [Change MACROS_RE](http://www.redmine.org/issues/3061) regexp not to stop - too early - in the issue description Textile wiki formatter is mentioned, - but in fact this change should be done for whatever wiki formatter you use. - * [Change arguments parsing](http://www.redmine.org/boards/3/topics/4987#message-9854) - again, - should be done for whatever wiki formatter you use. - * For some of the formatters escaping should be avoided for - macro arguments, see how it is done for Markdown Extra wiki formatter. - - [Preliminary version of patch](http://www.redmine.org/boards/3/topics/10649#message-15222) for Textile support was made available by Yuya Nishihara, according to the author "It works but really messy" but I haven't tested it so cannot comment on it. + Do not use commas in macro because it would be splited in different arguments and therefore plugin will not work. 7. To allow passing attachments names as macros arguments Redmine core should be patched accordingly: here's [the patch for Redmine 1.0.2](http://www.ndl.kiev.ua/downloads/redmine-1.0.2-attachments.patch) and here is [the patch for Redmine 0.9.x](http://www.ndl.kiev.ua/downloads/redmine-attachments-in-macros.patch.gz). @@ -109,7 +104,7 @@ Example of usage: {{graphviz( digraph finite_state_machine { rankdir=LR; - size="8,5" + size="8.5" node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; node [shape = circle]; LR_0 -> LR_2 [ label = "SS(B)" ]; diff --git a/app/controllers/wiki_external_filter_controller.rb b/app/controllers/wiki_external_filter_controller.rb index af0e553..4c73376 100644 --- a/app/controllers/wiki_external_filter_controller.rb +++ b/app/controllers/wiki_external_filter_controller.rb @@ -10,7 +10,9 @@ class WikiExternalFilterController < ApplicationController filename = params[:filename] ? params[:filename] : name config = load_config cache_key = self.construct_cache_key(macro, name) - content = read_fragment cache_key + content = Rails.cache.read cache_key + + Rails.logger.debug "Config:#{config} Key: #{cache_key} Content: #{content}" if (content) send_data content[index], :type => config[macro]['outputs'][index]['content_type'], :disposition => 'inline', :filename => filename diff --git a/app/helpers/wiki_external_filter_helper.rb b/app/helpers/wiki_external_filter_helper.rb index a26905b..f8721d0 100644 --- a/app/helpers/wiki_external_filter_helper.rb +++ b/app/helpers/wiki_external_filter_helper.rb @@ -1,14 +1,15 @@ require 'digest/sha2' +include Redmine::WikiFormatting::Macros::Definitions module WikiExternalFilterHelper def load_config unless @config - config_file = "#{RAILS_ROOT}/config/wiki_external_filter.yml" + config_file = "#{Rails.root}/plugins/wiki_external_filter/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] + @config = YAML.load_file(config_file)[Rails.env] end @config end @@ -26,7 +27,7 @@ module WikiExternalFilterHelper def build(text, attachments, macro, info) - name = Digest::SHA256.hexdigest(text) + name = Digest::SHA256.hexdigest(text.to_s) result = {} content = nil cache_key = nil @@ -41,27 +42,29 @@ module WikiExternalFilterHelper if expires > 0 cache_key = self.construct_cache_key(macro, name) begin - content = read_fragment cache_key, :expires_in => expires.seconds + content = Rails.cache.read cache_key, :expires_in => expires.seconds rescue - RAILS_DEFAULT_LOGGER.error "Failed to load cache: #{cache_key}, error: $!" + Rails.logger.error "Failed to load cache: #{cache_key}, error: $! #{error} #{$@}" end end if content - result[:source] = text + result[:source] = text.to_s result[:content] = content - RAILS_DEFAULT_LOGGER.debug "from cache: #{cache_key}" + Rails.logger.debug "from cache: #{cache_key}" else result = self.build_forced(text, attachments, info) if result[:status] if expires > 0 begin - write_fragment cache_key, result[:content], :expires_in => expires.seconds - RAILS_DEFAULT_LOGGER.debug "cache saved: #{cache_key}" + Rails.cache.write cache_key, result[:content], :expires_in => expires.seconds + Rails.logger.debug "cache saved: #{cache_key} expires #{expires.seconds}" rescue - RAILS_DEFAULT_LOGGER.error "Failed to save cache: #{cache_key}, error: $!" - end - end + Rails.logger.error "Failed to save cache: #{cache_key}, result content #{result[:content]}, error: $!" + end + else + raise "please set expires time under plugins settings" + end else raise "Error applying external filter: stdout is #{result[:content]}, stderr is #{result[:errors]}" end @@ -79,7 +82,7 @@ module WikiExternalFilterHelper if info['replace_attachments'] and attachments attachments.each do |att| - text.gsub!(/#{att.filename.downcase}/i, att.diskfile) + text.to_s.gsub!(/#{att.filename.downcase}/i, att.diskfile) end end @@ -87,8 +90,11 @@ module WikiExternalFilterHelper content = [] errors = "" + text = text.first.to_s.gsub("
", "\n") + Rails.logger.debug "\n Text #{text} \n" + info['outputs'].each do |out| - RAILS_DEFAULT_LOGGER.info "executing command: #{out['command']}" + Rails.logger.info "executing command: #{out['command']}" c = nil e = nil @@ -100,7 +106,7 @@ module WikiExternalFilterHelper Open4::popen4(out['command']) { |pid, fin, fout, ferr| fin.write out['prolog'] if out.key?('prolog') - fin.write CGI.unescapeHTML(text) + fin.write text fin.write out['epilog'] if out.key?('epilog') fin.close c, e = [fout.read, ferr.read] @@ -108,14 +114,14 @@ module WikiExternalFilterHelper rescue LoadError IO.popen(out['command'], 'r+b') { |f| f.write out['prolog'] if out.key?('prolog') - f.write CGI.unescapeHTML(text) + f.write text f.write out['epilog'] if out.key?('epilog') f.close_write c = f.read - } + } end - RAILS_DEFAULT_LOGGER.debug("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}") + Rails.logger.debug("child status: sig=#{$?.termsig}, exit=#{$?.exitstatus}") content << c errors += e if e diff --git a/app/views/wiki_external_filter/_settings.html.erb b/app/views/wiki_external_filter/_settings.html.erb index 61d1687..e8f3f14 100644 --- a/app/views/wiki_external_filter/_settings.html.erb +++ b/app/views/wiki_external_filter/_settings.html.erb @@ -10,7 +10,7 @@ Configuration example for ActiveSupport::Cache::FileStore, config/environments/production.rb file:

...
- config.action_controller.cache_store = :file_store, "#{RAILS_ROOT}/cache"
+ config.action_controller.cache_store = :file_store, "#{Rails.root}/cache"
...

@@ -18,8 +18,8 @@

Current cache settings are:
- ActionController::Base.cache_configured? = <%= h ActionController::Base.cache_configured? ? "true" : "false" %>
- <% cache_store = ActionController::Base.respond_to?('fragment_cache_store=') ? ActionController::Base.fragment_cache_store : ActionController::Base.cache_store %> + <%= h ActionController::Base.perform_caching ? "true" : "false" %>
+ <% cache_store = ActionController::Base.respond_to?('cache_store=') ? ActionController::Base.cache_store : ActionController::Base.cache_store %> ActionController::Base.cache_store = <%= h cache_store.inspect %>

diff --git a/config/routes.rb b/config/routes.rb index db7d3d4..f96b5d1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,3 @@ -ActionController::Routing::Routes.draw do |map| - map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video', :index => '1', :requirements => { :filename => /video\.flv/ } - map.connect 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video_url', :index => '1', :requirements => { :filename => /video_url\.flv/ } -end +match 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video', :index => '1', :requirements => { :filename => /video\.flv/ } +match 'wiki_external_filter/:filename', :controller => 'wiki_external_filter', :action => 'filter', :macro => 'video_url', :index => '1', :requirements => { :filename => /video_url\.flv/ } +match '/wiki_external_filter', :to => 'wiki_external_filter#filter', :via => [:get, :post] diff --git a/init.rb b/init.rb index 7034947..dc11a4f 100644 --- a/init.rb +++ b/init.rb @@ -1,6 +1,7 @@ require 'redmine' +require "#{Rails.root}/plugins/wiki_external_filter/app/helpers/wiki_external_filter_helper" -RAILS_DEFAULT_LOGGER.info 'Starting wiki_external_filter plugin for Redmine' +Rails.logger.info 'Starting wiki_external_filter plugin for Redmin' Redmine::Plugin.register :wiki_external_filter do name 'Wiki External Filter Plugin' @@ -8,19 +9,21 @@ Redmine::Plugin.register :wiki_external_filter do description 'Processes given text using external command and renders its output' author_url 'http://www.ndl.kiev.ua' version '0.0.2' + requires_redmine :version_or_higher => '2.0.0' + settings :default => {'cache_seconds' => '0'}, :partial => 'wiki_external_filter/settings' config = WikiExternalFilterHelper.load_config - RAILS_DEFAULT_LOGGER.debug "Config: #{config.inspect}" + Rails.logger.debug "Config: #{config.inspect}" config.keys.each do |name| - RAILS_DEFAULT_LOGGER.info "Registering #{name} macro with wiki_external_filter" + Rails.logger.info "Registering #{name} macro with wiki_external_filter" Redmine::WikiFormatting::Macros.register do info = config[name] desc info['description'] macro name do |obj, args| - m = WikiExternalFilterHelper::Macro.new(self, args.to_s, obj.respond_to?('page') ? obj.page.attachments : nil, name, info) - m.render + m = WikiExternalFilterHelper::Macro.new(self, args, obj.respond_to?('page') ? obj.page.attachments : nil, name, info) + m.render end # code borrowed from wiki latex plugin