##// END OF EJS Templates
Added request and controller objects to the hooks by default....
Eric Davis -
r2368:5b7a5c39a7da
parent child
Show More
@@ -17,6 +17,8
17 17
18 18 module Redmine
19 19 module Hook
20 include ActionController::UrlWriter
21
20 22 @@listener_classes = []
21 23 @@listeners = nil
22 24 @@hook_listeners = {}
@@ -55,11 +57,22 module Redmine
55 57 # Calls a hook.
56 58 # Returns the listeners response.
57 59 def call_hook(hook, context={})
58 response = ''
59 hook_listeners(hook).each do |listener|
60 response << listener.send(hook, context).to_s
60 returning [] do |response|
61 hls = hook_listeners(hook)
62 if hls.any?
63 request = context[:request]
64 if request
65 default_url_options[:host] ||= request.env["SERVER_NAME"]
66 # Only set port if it's requested and isn't port 80. Otherwise a url
67 # like: +http://example.com:/url+ may be generated
68 if request.env["SERVER_PORT"] && request.env["SERVER_PORT"] != 80
69 default_url_options[:port] ||= request.env["SERVER_PORT"]
70 end
71 default_url_options[:protocol] ||= request.protocol
72 end
73 hls.each {|listener| response << listener.send(hook, context)}
74 end
61 75 end
62 response
63 76 end
64 77 end
65 78
@@ -91,17 +104,48 module Redmine
91 104 include ActionView::Helpers::TextHelper
92 105 include ActionController::UrlWriter
93 106 include ApplicationHelper
107
108 # Helper method to directly render a partial using the context:
109 #
110 # class MyHook < Redmine::Hook::ViewListener
111 # render_on :view_issues_show_details_bottom, :partial => "show_more_data"
112 # end
113 #
114 def self.render_on(hook, options={})
115 define_method hook do |context|
116 context[:controller].send(:render_to_string, {:locals => context}.merge(options))
117 end
118 end
94 119 end
95 120
96 # Helper module included in ApplicationHelper so that hooks can be called
97 # in views like this:
121 # Helper module included in ApplicationHelper and ActionControllerso that
122 # hooks can be called in views like this:
123 #
98 124 # <%= call_hook(:some_hook) %>
99 125 # <%= call_hook(:another_hook, :foo => 'bar' %>
100 126 #
101 # Current project is automatically added to the call context.
127 # Or in controllers like:
128 # call_hook(:some_hook)
129 # call_hook(:another_hook, :foo => 'bar'
130 #
131 # Hooks added to views will be concatenated into a string. Hooks added to
132 # controllers will return an array of results.
133 #
134 # Several objects are automatically added to the call context:
135 #
136 # * project => current project
137 # * request => Request instance
138 # * controller => current Controller instance
139 #
102 140 module Helper
103 141 def call_hook(hook, context={})
104 Redmine::Hook.call_hook(hook, {:project => @project}.merge(context))
142 if is_a?(ActionController::Base)
143 ctx = {:controller => self, :project => @project, :request => request}
144 Redmine::Hook.call_hook(hook, ctx.merge(context))
145 else
146 ctx = {:controller => controller, :project => @project, :request => request}
147 Redmine::Hook.call_hook(hook, ctx.merge(context)).join(' ')
148 end
105 149 end
106 150 end
107 151 end
@@ -20,7 +20,7 require File.dirname(__FILE__) + '/../../../test_helper'
20 20 class Redmine::Hook::ManagerTest < Test::Unit::TestCase
21 21
22 22 # Some hooks that are manually registered in these tests
23 class TestHook < Redmine::Hook::Listener; end
23 class TestHook < Redmine::Hook::ViewListener; end
24 24
25 25 class TestHook1 < TestHook
26 26 def view_layouts_base_html_head(context)
@@ -39,6 +39,13 class Redmine::Hook::ManagerTest < Test::Unit::TestCase
39 39 "Context keys: #{context.keys.collect(&:to_s).sort.join(', ')}."
40 40 end
41 41 end
42
43 class TestLinkToHook < TestHook
44 def view_layouts_base_html_head(context)
45 link_to('Issues', :controller => 'issues')
46 end
47 end
48
42 49 Redmine::Hook.clear_listeners
43 50
44 51 def setup
@@ -47,6 +54,7 class Redmine::Hook::ManagerTest < Test::Unit::TestCase
47 54
48 55 def teardown
49 56 @hook_module.clear_listeners
57 @hook_module.default_url_options = { }
50 58 end
51 59
52 60 def test_clear_listeners
@@ -67,17 +75,84 class Redmine::Hook::ManagerTest < Test::Unit::TestCase
67 75
68 76 def test_call_hook
69 77 @hook_module.add_listener(TestHook1)
70 assert_equal 'Test hook 1 listener.', @hook_module.call_hook(:view_layouts_base_html_head)
78 assert_equal ['Test hook 1 listener.'], @hook_module.call_hook(:view_layouts_base_html_head)
71 79 end
72 80
73 81 def test_call_hook_with_context
74 82 @hook_module.add_listener(TestHook3)
75 assert_equal 'Context keys: bar, foo.', @hook_module.call_hook(:view_layouts_base_html_head, :foo => 1, :bar => 'a')
83 assert_equal ['Context keys: bar, foo.'], @hook_module.call_hook(:view_layouts_base_html_head, :foo => 1, :bar => 'a')
76 84 end
77 85
78 86 def test_call_hook_with_multiple_listeners
79 87 @hook_module.add_listener(TestHook1)
80 88 @hook_module.add_listener(TestHook2)
81 assert_equal 'Test hook 1 listener.Test hook 2 listener.', @hook_module.call_hook(:view_layouts_base_html_head)
89 assert_equal ['Test hook 1 listener.', 'Test hook 2 listener.'], @hook_module.call_hook(:view_layouts_base_html_head)
90 end
91
92 # Context: Redmine::Hook::call_hook
93 def test_call_hook_default_url_options_set
94 request = ActionController::TestRequest.new
95 request.env = { "SERVER_NAME" => 'example.com'}
96 @hook_module.add_listener(TestLinkToHook)
97
98 assert_equal ['<a href="http://example.com/issues">Issues</a>'],
99 @hook_module.call_hook(:view_layouts_base_html_head, :request => request)
100 end
101
102 def test_call_hook_default_url_options_set_with_no_standard_request_port
103 request = ActionController::TestRequest.new
104 request.env = { "SERVER_NAME" => 'example.com', "SERVER_PORT" => 3000}
105 @hook_module.add_listener(TestLinkToHook)
106
107 assert_equal ['<a href="http://example.com:3000/issues">Issues</a>'],
108 @hook_module.call_hook(:view_layouts_base_html_head, :request => request)
109 end
110
111 def test_call_hook_default_url_options_set_with_ssl
112 request = ActionController::TestRequest.new
113 request.env = { "SERVER_NAME" => 'example.com', "HTTPS" => 'on'}
114 @hook_module.add_listener(TestLinkToHook)
115
116 assert_equal ['<a href="https://example.com/issues">Issues</a>'],
117 @hook_module.call_hook(:view_layouts_base_html_head, :request => request)
118 end
119
120 def test_call_hook_default_url_options_set_with_forwarded_ssl
121 request = ActionController::TestRequest.new
122 request.env = { "SERVER_NAME" => 'example.com', "HTTP_X_FORWARDED_PROTO" => "https"}
123 @hook_module.add_listener(TestLinkToHook)
124
125 assert_equal ['<a href="https://example.com/issues">Issues</a>'],
126 @hook_module.call_hook(:view_layouts_base_html_head, :request => request)
127 end
128
129 # Context: Redmine::Hook::Helper.call_hook
130 def test_call_hook_with_project_added_to_context
131 # TODO: Implement test
132 end
133
134 def test_call_hook_from_controller_with_controller_added_to_context
135 # TODO: Implement test
136 end
137
138 def test_call_hook_from_controller_with_request_added_to_context
139 # TODO: Implement test
140 end
141
142 def test_call_hook_from_view_with_project_added_to_context
143 # TODO: Implement test
144 end
145
146 def test_call_hook_from_view_with_controller_added_to_context
147 # TODO: Implement test
148 end
149
150 def test_call_hook_from_view_with_request_added_to_context
151 # TODO: Implement test
152 end
153
154 def test_call_hook_from_view_should_join_responses_with_a_space
155 # TODO: Implement test
82 156 end
83 157 end
158
General Comments 0
You need to be logged in to leave comments. Login now