From 862c9e0fdebe28c77240acffaad041b124c8046f Mon Sep 17 00:00:00 2001
From: Holger Just <h.just@finn.de>
Date: Sun, 20 Nov 2011 00:59:52 +0100
Subject: [PATCH] [#604] Adapt the upstream include mechanism to work with Wiki
 pages

---
 lib/chili_project/liquid.rb              |  1 +
 lib/chili_project/liquid/file_system.rb  | 18 ++++++
 lib/chili_project/liquid/tags.rb         |  4 +-
 lib/chili_project/liquid/tags/include.rb | 82 ++++++++++++++++++++++++
 lib/redmine/wiki_formatting/macros.rb    | 13 ----
 5 files changed, 103 insertions(+), 15 deletions(-)
 create mode 100644 lib/chili_project/liquid/file_system.rb
 create mode 100644 lib/chili_project/liquid/tags/include.rb

diff --git a/lib/chili_project/liquid.rb b/lib/chili_project/liquid.rb
index 9dae8d246..d9da7d5b9 100644
--- a/lib/chili_project/liquid.rb
+++ b/lib/chili_project/liquid.rb
@@ -3,5 +3,6 @@ require 'chili_project/liquid/tags'
 
 module ChiliProject
   module Liquid
+    Liquid::Template.file_system = FileSystem.new
   end
 end
\ No newline at end of file
diff --git a/lib/chili_project/liquid/file_system.rb b/lib/chili_project/liquid/file_system.rb
new file mode 100644
index 000000000..d6fe60f95
--- /dev/null
+++ b/lib/chili_project/liquid/file_system.rb
@@ -0,0 +1,18 @@
+module ChiliProject
+  module Liquid
+    class FileSystem
+      def read_template_file(template_name, context)
+        raise ::Liquid::FileSystemError.new("Page not found") if template_name.blank?
+        project = Project.find(context['project'].identifier) if context['project'].present?
+
+        cross_project_page = template_name.include?(':')
+        page = Wiki.find_page(template_name.to_s.strip, :project => (cross_project_page ? nil : project))
+        if page.nil? || !page.visible?
+          raise ::Liquid::FileSystemError.new("No such page '#{template_name}'")
+        end
+
+        page.content
+      end
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/chili_project/liquid/tags.rb b/lib/chili_project/liquid/tags.rb
index e44ab0ea7..41a28f7b3 100644
--- a/lib/chili_project/liquid/tags.rb
+++ b/lib/chili_project/liquid/tags.rb
@@ -23,10 +23,9 @@ module ChiliProject::Liquid
       end
     end
 
-    # TODO: reimplement old macros as tags and register them here
     register_tag('child_pages', ChildPages, :html => true)
     register_tag('hello_world', HelloWorld)
-    # include
+    register_tag('include', Include, :html => true)
     register_tag('tag_list', TagList, :html => true)
     register_tag('variable_list', VariableList, :html => true)
   end
@@ -36,3 +35,4 @@ end
 # existing pages to the new syntax.
 ChiliProject::Liquid::Legacy.add('child_pages', :tag)
 ChiliProject::Liquid::Legacy.add('hello_world', :tag)
+ChiliProject::Liquid::Legacy.add('include', :tag)
diff --git a/lib/chili_project/liquid/tags/include.rb b/lib/chili_project/liquid/tags/include.rb
new file mode 100644
index 000000000..6de3df92c
--- /dev/null
+++ b/lib/chili_project/liquid/tags/include.rb
@@ -0,0 +1,82 @@
+#-- copyright
+# ChiliProject is a project management system.
+#
+# Copyright (C) 2010-2011 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# See doc/COPYRIGHT.rdoc for more details.
+#++
+
+module ChiliProject::Liquid::Tags
+  class Include < ::Liquid::Include
+
+    # This method follows the basic flow of the default include in liquid
+    # We just add some additional flexibility. This method can be removed once
+    # https://github.com/Shopify/liquid/pull/78 got accepted
+    def render(context)
+      context.stack do
+        template = _read_template_from_file_system(context)
+        partial = Liquid::Template.parse _template_source(template)
+        variable = context[@variable_name || @template_name[1..-2]]
+
+        @attributes.each do |key, value|
+          context[key] = context[value]
+        end
+
+        if variable.is_a?(Array)
+          variable.collect do |variable|
+            context[@template_name[1..-2]] = variable
+            _render_partial(partial, template, context)
+          end
+        else
+          context[@template_name[1..-2]] = variable
+          _render_partial(partial, template, context)
+        end
+      end
+    end
+
+  private
+    def break_circle(context)
+      context.registers[:included_pages] ||= []
+
+      project = context['project'].identifier if context['project'].present?
+      template_name = context[@template_name]
+      cross_project_page = template_name.include?(':')
+      page_title = cross_project_page ? template_name : "#{project}:#{template_name}"
+
+      raise ::Liquid::FileSystemError.new("Circular inclusion detected") if context.registers[:included_pages].include?(page_title)
+      context.registers[:included_pages] << page_title
+
+      yield
+    ensure
+      context.registers[:included_pages].pop
+    end
+
+    def _template_source(wiki_content)
+      wiki_content.text
+    end
+
+    def _render_partial(partial, template, context)
+      break_circle(context) do
+        textile = partial.render(context)
+
+        # Call textilizable on the view so all of the helpers are loaded
+        # based on the view and not this tag
+        context.registers[:view].textilizable(textile, :attachments => template.page.attachments, :headings => false, :object => template)
+      end
+    end
+
+    def _read_template_from_file_system(context)
+      wiki_content = super
+
+      # Set the new project to that additional includes use the correct
+      # base project
+      context['project'] = wiki_content.page.wiki.project
+      wiki_content
+    end
+  end
+end
diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb
index b343b4f2b..faef7a8bc 100644
--- a/lib/redmine/wiki_formatting/macros.rb
+++ b/lib/redmine/wiki_formatting/macros.rb
@@ -66,19 +66,6 @@ module Redmine
           @@desc = txt
         end
       end
-
-      # Builtin macros
-      desc "Include a wiki page. Example:\n\n  !{{include(Foo)}}\n\nor to include a page of a specific project wiki:\n\n  !{{include(projectname:Foo)}}"
-      macro :include do |obj, args|
-        page = Wiki.find_page(args.first.to_s, :project => @project)
-        raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
-        @included_wiki_pages ||= []
-        raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
-        @included_wiki_pages << page.title
-        out = textilizable(page.content, :text, :attachments => page.attachments, :headings => false)
-        @included_wiki_pages.pop
-        out
-      end
     end
   end
 end
-- 
GitLab