Index: test/unit/lib/redmine/plugin_test.rb
===================================================================
--- test/unit/lib/redmine/plugin_test.rb (revision 0)
+++ test/unit/lib/redmine/plugin_test.rb (revision 0)
@@ -0,0 +1,20 @@
+require File.dirname(__FILE__) + '/../../../test_helper'
+
+class Redmine::PluginTest < Test::Unit::TestCase
+ def test_sanity
+ assert true
+ end
+
+ def test_add_hook
+ assert_equal false, Redmine::Plugin::Hook::Manager.hook_registered?(:issue_show)
+ Redmine::Plugin.add_hook(:issue_show, Proc.new { })
+ assert Redmine::Plugin::Hook::Manager.hook_registered?(:issue_show)
+ end
+
+ def test_add_hook_invalid
+ assert_equal false, Redmine::Plugin::Hook::Manager.hook_registered?(:invalid)
+ Redmine::Plugin.add_hook(:invalid, Proc.new { })
+ assert Redmine::Plugin::Hook::Manager.hook_registered?(:invalid)
+ end
+end
+
Index: test/unit/lib/redmine/plugin_hook_test.rb
===================================================================
--- test/unit/lib/redmine/plugin_hook_test.rb (revision 0)
+++ test/unit/lib/redmine/plugin_hook_test.rb (revision 0)
@@ -0,0 +1,128 @@
+require File.dirname(__FILE__) + '/../../../test_helper'
+
+class Redmine::Plugin::Hook::ManagerTest < Test::Unit::TestCase
+ def setup
+ @manager = Redmine::Plugin::Hook::Manager
+ end
+
+ def teardown
+ @manager.clear_listeners
+ end
+
+ def test_sanity
+ assert true
+ end
+
+ def test_hook_format
+ assert_kind_of Hash, @manager::hooks
+ @manager::hooks.each do |hook, registrations|
+ assert_kind_of Symbol, hook
+ assert_kind_of Array, registrations
+ assert_equal 0, registrations.length
+ end
+ end
+
+ def test_valid_hook
+ assert @manager::valid_hook?(:issue_show)
+ end
+
+ def test_invalid_hook
+ assert_equal false, @manager::valid_hook?(:an_invalid_hook_name)
+ end
+
+ def test_clear_listeners
+ assert_equal 0, @manager::hooks[:issue_show].length
+ @manager.add_listener(:issue_show, Proc.new { } )
+ @manager.add_listener(:issue_show, Proc.new { } )
+ @manager.add_listener(:issue_show, Proc.new { } )
+ @manager.add_listener(:issue_show, Proc.new { } )
+ assert_equal 4, @manager::hooks[:issue_show].length
+
+ @manager.clear_listeners
+ assert_equal 0, @manager::hooks[:issue_show].length
+ end
+
+ def test_add_listener
+ assert_equal 0, @manager::hooks[:issue_show].length
+ @manager.add_listener(:issue_show, Proc.new { } )
+ assert_equal 1, @manager::hooks[:issue_show].length
+ end
+
+ def test_add_invalid_listener
+ hooks = @manager::hooks
+ @manager.add_listener(:invalid, Proc.new { } )
+ assert_equal hooks, @manager::hooks
+ end
+
+ def test_call_hook_with_response
+ function = Proc.new { return 'response' }
+
+ @manager.add_listener(:issue_show, function)
+
+ assert_equal 'response', @manager.call_hook(:issue_show)
+ end
+
+ def test_call_multiple_hooks_with_response
+ function1 = Proc.new { return 'First Call.' }
+ function2 = Proc.new { return 'Second Call.' }
+ function3 = Proc.new { return 'Third Call.' }
+
+ @manager.add_listener(:issue_show, function1)
+ @manager.add_listener(:issue_show, function2)
+ @manager.add_listener(:issue_show, function3)
+
+ assert_equal 'First Call.Second Call.Third Call.', @manager.call_hook(:issue_show)
+ end
+
+ def test_call_hook_without_response
+ function = Proc.new { }
+
+ @manager.add_listener(:issue_show, function)
+
+ assert_equal '', @manager.call_hook(:issue_show)
+ end
+
+ def test_call_multiple_hooks_without_responses
+ function1 = Proc.new { }
+ function2 = Proc.new { }
+ function3 = Proc.new { }
+
+ @manager.add_listener(:issue_show, function1)
+ @manager.add_listener(:issue_show, function2)
+ @manager.add_listener(:issue_show, function3)
+
+ assert_equal '', @manager.call_hook(:issue_show)
+ end
+
+ def test_hook_registered_yes
+ @manager.add_listener(:issue_show, Proc.new { })
+ assert @manager.hook_registered?(:issue_show)
+ end
+
+ def test_hook_registered_no
+ assert_equal false, @manager.hook_registered?(:issue_show)
+ end
+end
+
+class Redmine::Plugin::Hook::BaseTest < Test::Unit::TestCase
+ def test_sanity
+ assert true
+ end
+
+ def test_help_should_be_a_singleton
+ assert Redmine::Plugin::Hook::Base::Helper.include?(Singleton)
+ end
+
+ def test_helper_should_include_actionview_helpers
+ [ActionView::Helpers::TagHelper,
+ ActionView::Helpers::FormHelper,
+ ActionView::Helpers::FormTagHelper,
+ ActionView::Helpers::FormOptionsHelper,
+ ActionView::Helpers::JavaScriptHelper,
+ ActionView::Helpers::PrototypeHelper,
+ ActionView::Helpers::NumberHelper,
+ ActionView::Helpers::UrlHelper].each do |helper|
+ assert Redmine::Plugin::Hook::Base::Helper.include?(helper), "#{helper} wasn't included."
+ end
+ end
+end
Index: app/helpers/issues_helper.rb
===================================================================
--- app/helpers/issues_helper.rb (revision 1709)
+++ app/helpers/issues_helper.rb (working copy)
@@ -86,7 +86,9 @@
when 'attachment'
label = l(:label_attachment)
end
-
+
+ Redmine::Plugin::Hook::Manager.call_hook(:issues_helper_show_details, {:detail => detail, :label => label, :value => value, :old_value => old_value })
+
label ||= detail.prop_key
value ||= detail.value
old_value ||= detail.old_value
Index: app/controllers/issues_controller.rb
===================================================================
--- app/controllers/issues_controller.rb (revision 1709)
+++ app/controllers/issues_controller.rb (working copy)
@@ -223,7 +223,6 @@
assigned_to = (params[:assigned_to_id].blank? || params[:assigned_to_id] == 'none') ? nil : User.find_by_id(params[:assigned_to_id])
category = (params[:category_id].blank? || params[:category_id] == 'none') ? nil : @project.issue_categories.find_by_id(params[:category_id])
fixed_version = (params[:fixed_version_id].blank? || params[:fixed_version_id] == 'none') ? nil : @project.versions.find_by_id(params[:fixed_version_id])
-
unsaved_issue_ids = []
@issues.each do |issue|
journal = issue.init_journal(User.current, params[:notes])
@@ -234,6 +233,9 @@
issue.start_date = params[:start_date] unless params[:start_date].blank?
issue.due_date = params[:due_date] unless params[:due_date].blank?
issue.done_ratio = params[:done_ratio] unless params[:done_ratio].blank?
+
+ Redmine::Plugin::Hook::Manager.call_hook(:issue_bulk_edit_save, {:params => params, :issue => issue })
+
# Don't save any change to the issue if the user is not authorized to apply the requested status
if (status.nil? || (issue.status.new_status_allowed_to?(status, current_role, issue.tracker) && issue.status = status)) && issue.save
# Send notification for each issue (if changed)
Index: app/views/projects/settings/_members.rhtml
===================================================================
--- app/views/projects/settings/_members.rhtml (revision 1709)
+++ app/views/projects/settings/_members.rhtml (working copy)
@@ -9,6 +9,7 @@
<%= l(:label_user) %>
<%= l(:label_role) %>
+ <%= Redmine::Plugin::Hook::Manager.call_hook(:project_member_list_header, {:project => @project }) %>