redmine-hooks-svn-1694.patch

Patch to add a Plugin Hook API - Eric Davis, 2008-07-24 06:14

Download (7.22 KB)

View differences:

app/helpers/issues_helper.rb (working copy)
86 86
    when 'attachment'
87 87
      label = l(:label_attachment)
88 88
    end
89

  
90
    Redmine::Plugin::Hook::Manager.call_hook(:issues_helper_show_details, {:detail => detail, :label => label, :value => value, :old_value => old_value })
89 91
       
90 92
    label ||= detail.prop_key
91 93
    value ||= detail.value
app/controllers/issues_controller.rb (working copy)
234 234
        issue.start_date = params[:start_date] unless params[:start_date].blank?
235 235
        issue.due_date = params[:due_date] unless params[:due_date].blank?
236 236
        issue.done_ratio = params[:done_ratio] unless params[:done_ratio].blank?
237

  
238
        Redmine::Plugin::Hook::Manager.call_hook(:issue_bulk_edit_save, {:params => params, :issue => issue })
239

  
237 240
        # Don't save any change to the issue if the user is not authorized to apply the requested status
238 241
        if (status.nil? || (issue.status.new_status_allowed_to?(status, current_role, issue.tracker) && issue.status = status)) && issue.save
239 242
          # Send notification for each issue (if changed)
app/views/projects/settings/_members.rhtml (working copy)
9 9
	<thead>
10 10
	  <th><%= l(:label_user) %></th>
11 11
	  <th><%= l(:label_role) %></th>
12
          <%= Redmine::Plugin::Hook::Manager.call_hook(:project_member_list_header, {:project => @project }) %>
12 13
	  <th style="width:15%"></th>
13 14
	</thead>
14 15
	<tbody>
......
24 25
      <% end %>
25 26
    <% end %>
26 27
    </td>
28
    <%= Redmine::Plugin::Hook::Manager.call_hook(:project_member_list_column_three, {:project => @project, :member => member }) %>
29

  
27 30
    <td align="center">
28 31
      <%= link_to_remote l(:button_delete), { :url => {:controller => 'members', :action => 'destroy', :id => member},                                              
29 32
                                              :method => :post
app/views/issues/bulk_edit.rhtml (working copy)
38 38
<label><%= l(:field_done_ratio) %>: 
39 39
<%= select_tag 'done_ratio', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></label>
40 40
</p>
41
<%= Redmine::Plugin::Hook::Manager.call_hook(:issue_bulk_edit, {:project => @project, :issue => @issues }) %>
41 42
</fieldset>
42 43

  
43 44
<fieldset><legend><%= l(:field_notes) %></legend>
app/views/issues/_form.rhtml (working copy)
48 48
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
49 49
<% end %>
50 50

  
51
<%= Redmine::Plugin::Hook::Manager.call_hook(:issue_edit, {:project => @project, :issue => @issue, :form => f }) %>
52

  
51 53
<%= wikitoolbar_for 'issue_description' %>
app/views/issues/show.rhtml (working copy)
53 53
 <%end
54 54
end %>
55 55
</tr>
56
<%= Redmine::Plugin::Hook::Manager.call_hook(:issue_show, {:project => @project, :issue => @issue}) %>
57
       
56 58
</table>
57 59
<hr />
58 60

  
lib/redmine/plugin.rb (working copy)
116 116
      self.instance_eval(&block)
117 117
      @project_module = nil
118 118
    end
119
    
120
    # Registers a +method+ to be called when Redmine runs a hook called
121
    # +hook_name+
122
    #
123
    #   # Run puts whenever the issue_show hook is called
124
    #   add_hook :issue_show, Proc.new { puts 'Hello' }
125
    #
126
    #   # Call the class method +my_method+ passing in all the context
127
    #   add_hook :issue_show, Proc.new {|context| MyPlugin.my_method(context)}
128
    def add_hook(hook_name, method)
129
      Redmine::Plugin::Hook::Manager.add_listener(hook_name, method)
130
    end
119 131

  
120 132
    # Returns +true+ if the plugin can be configured.
121 133
    def configurable?
122 134
      settings && settings.is_a?(Hash) && !settings[:partial].blank?
123 135
    end
136
    
137
    # Hook is used to allow plugins to hook into Redmine at specific sections
138
    # to change it's behavior.  See +Redmine::Plugin.add_hook+ for details.
139
    class Hook
140
      
141
      class Manager
142
        # Hooks and the procs added
143
        @@hooks = {
144
          :issue_show => [],
145
          :issue_edit => [],
146
          :issue_bulk_edit => [],
147
          :issue_bulk_edit_save => [],
148
          :issue_update => [],
149
          :project_member_list_header => [],
150
          :project_member_list_column_three => [],
151
          :issues_helper_show_details => []
152
        }
153
        
154
        cattr_reader :hooks
155
        
156
        class << self
157
          
158
          def valid_hook?(hook_name)
159
            return @@hooks.has_key?(hook_name)
160
          end
161

  
162
          # Add +method+ to +hook_name+
163
          def add_listener(hook_name, method)
164
            if valid_hook?(hook_name)
165
              @@hooks[hook_name.to_sym] << method
166
              puts "Listener added for #{hook_name.to_s}"
167
            end
168
          end
169
          
170
          # Run all the hooks for +hook_name+ passing in +context+
171
          def call_hook(hook_name, context = { })
172
            response = ''
173

  
174
            if hook_registered?(hook_name)
175
              @@hooks[hook_name.to_sym].each do |method|
176
                response += method.call(context)
177
              end
178
            end
179

  
180
            return response
181
          end
182

  
183
          # Are hooks registered for +hook_name+
184
          def hook_registered?(hook_name)
185
            return @@hooks[hook_name.to_sym].size > 0
186
          end
187
        end
188
      end
189
      
190
      # Base class for Redmin Plugin hooks.
191
      class Base
192
  
193
        # Class level access to Rails' helper methods.
194
        def self.help
195
          Helper.instance
196
        end
197

  
198
        # Includes several Helper methods to be used in the class
199
        class Helper # :nodoc:
200
          include Singleton
201
          include ERB::Util
202
          include ActionView::Helpers::TagHelper
203
          include ActionView::Helpers::FormHelper
204
          include ActionView::Helpers::FormTagHelper
205
          include ActionView::Helpers::FormOptionsHelper
206
          include ActionView::Helpers::JavaScriptHelper 
207
          include ActionView::Helpers::PrototypeHelper
208
          include ActionView::Helpers::NumberHelper
209
          include ActionView::Helpers::UrlHelper
210
          
211
          include ActionController::UrlWriter 
212

  
213
          def protect_against_forgery? # :nodoc:
214
            false
215
          end
216
          
217
        end
218

  
219
      end
220
    end
221
    
124 222
  end
125 223
end