##// END OF EJS Templates
Fixed: child_pages macro fails on wiki page history (#4152)....
Jean-Philippe Lang -
r2892:4ea714fb911b
parent child
Show More
@@ -1,121 +1,121
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module Redmine
18 module Redmine
19 module WikiFormatting
19 module WikiFormatting
20 module Macros
20 module Macros
21 module Definitions
21 module Definitions
22 def exec_macro(name, obj, args)
22 def exec_macro(name, obj, args)
23 method_name = "macro_#{name}"
23 method_name = "macro_#{name}"
24 send(method_name, obj, args) if respond_to?(method_name)
24 send(method_name, obj, args) if respond_to?(method_name)
25 end
25 end
26
26
27 def extract_macro_options(args, *keys)
27 def extract_macro_options(args, *keys)
28 options = {}
28 options = {}
29 while args.last.to_s.strip =~ %r{^(.+)\=(.+)$} && keys.include?($1.downcase.to_sym)
29 while args.last.to_s.strip =~ %r{^(.+)\=(.+)$} && keys.include?($1.downcase.to_sym)
30 options[$1.downcase.to_sym] = $2
30 options[$1.downcase.to_sym] = $2
31 args.pop
31 args.pop
32 end
32 end
33 return [args, options]
33 return [args, options]
34 end
34 end
35 end
35 end
36
36
37 @@available_macros = {}
37 @@available_macros = {}
38
38
39 class << self
39 class << self
40 # Called with a block to define additional macros.
40 # Called with a block to define additional macros.
41 # Macro blocks accept 2 arguments:
41 # Macro blocks accept 2 arguments:
42 # * obj: the object that is rendered
42 # * obj: the object that is rendered
43 # * args: macro arguments
43 # * args: macro arguments
44 #
44 #
45 # Plugins can use this method to define new macros:
45 # Plugins can use this method to define new macros:
46 #
46 #
47 # Redmine::WikiFormatting::Macros.register do
47 # Redmine::WikiFormatting::Macros.register do
48 # desc "This is my macro"
48 # desc "This is my macro"
49 # macro :my_macro do |obj, args|
49 # macro :my_macro do |obj, args|
50 # "My macro output"
50 # "My macro output"
51 # end
51 # end
52 # end
52 # end
53 def register(&block)
53 def register(&block)
54 class_eval(&block) if block_given?
54 class_eval(&block) if block_given?
55 end
55 end
56
56
57 private
57 private
58 # Defines a new macro with the given name and block.
58 # Defines a new macro with the given name and block.
59 def macro(name, &block)
59 def macro(name, &block)
60 name = name.to_sym if name.is_a?(String)
60 name = name.to_sym if name.is_a?(String)
61 @@available_macros[name] = @@desc || ''
61 @@available_macros[name] = @@desc || ''
62 @@desc = nil
62 @@desc = nil
63 raise "Can not create a macro without a block!" unless block_given?
63 raise "Can not create a macro without a block!" unless block_given?
64 Definitions.send :define_method, "macro_#{name}".downcase, &block
64 Definitions.send :define_method, "macro_#{name}".downcase, &block
65 end
65 end
66
66
67 # Sets description for the next macro to be defined
67 # Sets description for the next macro to be defined
68 def desc(txt)
68 def desc(txt)
69 @@desc = txt
69 @@desc = txt
70 end
70 end
71 end
71 end
72
72
73 # Builtin macros
73 # Builtin macros
74 desc "Sample macro."
74 desc "Sample macro."
75 macro :hello_world do |obj, args|
75 macro :hello_world do |obj, args|
76 "Hello world! Object: #{obj.class.name}, " + (args.empty? ? "Called with no argument." : "Arguments: #{args.join(', ')}")
76 "Hello world! Object: #{obj.class.name}, " + (args.empty? ? "Called with no argument." : "Arguments: #{args.join(', ')}")
77 end
77 end
78
78
79 desc "Displays a list of all available macros, including description if available."
79 desc "Displays a list of all available macros, including description if available."
80 macro :macro_list do
80 macro :macro_list do
81 out = ''
81 out = ''
82 @@available_macros.keys.collect(&:to_s).sort.each do |macro|
82 @@available_macros.keys.collect(&:to_s).sort.each do |macro|
83 out << content_tag('dt', content_tag('code', macro))
83 out << content_tag('dt', content_tag('code', macro))
84 out << content_tag('dd', textilizable(@@available_macros[macro.to_sym]))
84 out << content_tag('dd', textilizable(@@available_macros[macro.to_sym]))
85 end
85 end
86 content_tag('dl', out)
86 content_tag('dl', out)
87 end
87 end
88
88
89 desc "Displays a list of child pages. With no argument, it displays the child pages of the current wiki page. Examples:\n\n" +
89 desc "Displays a list of child pages. With no argument, it displays the child pages of the current wiki page. Examples:\n\n" +
90 " !{{child_pages}} -- can be used from a wiki page only\n" +
90 " !{{child_pages}} -- can be used from a wiki page only\n" +
91 " !{{child_pages(Foo)}} -- lists all children of page Foo\n" +
91 " !{{child_pages(Foo)}} -- lists all children of page Foo\n" +
92 " !{{child_pages(Foo, parent=1)}} -- same as above with a link to page Foo"
92 " !{{child_pages(Foo, parent=1)}} -- same as above with a link to page Foo"
93 macro :child_pages do |obj, args|
93 macro :child_pages do |obj, args|
94 args, options = extract_macro_options(args, :parent)
94 args, options = extract_macro_options(args, :parent)
95 page = nil
95 page = nil
96 if args.size > 0
96 if args.size > 0
97 page = Wiki.find_page(args.first.to_s, :project => @project)
97 page = Wiki.find_page(args.first.to_s, :project => @project)
98 elsif obj.is_a?(WikiContent)
98 elsif obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)
99 page = obj.page
99 page = obj.page
100 else
100 else
101 raise 'With no argument, this macro can be called from wiki pages only.'
101 raise 'With no argument, this macro can be called from wiki pages only.'
102 end
102 end
103 raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
103 raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
104 pages = ([page] + page.descendants).group_by(&:parent_id)
104 pages = ([page] + page.descendants).group_by(&:parent_id)
105 render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id)
105 render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id)
106 end
106 end
107
107
108 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)}}"
108 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)}}"
109 macro :include do |obj, args|
109 macro :include do |obj, args|
110 page = Wiki.find_page(args.first.to_s, :project => @project)
110 page = Wiki.find_page(args.first.to_s, :project => @project)
111 raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
111 raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
112 @included_wiki_pages ||= []
112 @included_wiki_pages ||= []
113 raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
113 raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.title)
114 @included_wiki_pages << page.title
114 @included_wiki_pages << page.title
115 out = textilizable(page.content, :text, :attachments => page.attachments)
115 out = textilizable(page.content, :text, :attachments => page.attachments)
116 @included_wiki_pages.pop
116 @included_wiki_pages.pop
117 out
117 out
118 end
118 end
119 end
119 end
120 end
120 end
121 end
121 end
General Comments 0
You need to be logged in to leave comments. Login now