File: lib/redmine/hook.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Redmine#18
  module: Hook#19
includes
  UrlWriter ( ActionController )
has properties
module method: add_listener / 1 #29
module method: listeners #36
module method: hook_listeners / 1 #41
module method: clear_listeners #46
module method: clear_listeners_instances #52
module method: call_hook / 2 #59
  class: Listener#70
includes
  Singleton ( Builtin-Module )
  I18n ( Redmine )
inherits from
  Object ( Builtin-Module )
has properties
class method: inherited / 1 #75
  class: ViewListener#84
  module: Helper#137
has properties
method: call_hook / 2 #138

Class Hierarchy

Object ( Builtin-Module )
Listener ( Redmine::Hook ) — #70
  ViewListener    #84

Code

   1  # Redmine - project management software
   2  # Copyright (C) 2006-2011  Jean-Philippe Lang
   3  #
   4  # This program is free software; you can redistribute it and/or
   5  # modify it under the terms of the GNU General Public License
   6  # as published by the Free Software Foundation; either version 2
   7  # of the License, or (at your option) any later version.
   8  #
   9  # This program is distributed in the hope that it will be useful,
  10  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  # GNU General Public License for more details.
  13  #
  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
  16  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17 
  18  module Redmine
  19    module Hook
  20      include ActionController::UrlWriter
  21 
  22      @@listener_classes = []
  23      @@listeners = nil
  24      @@hook_listeners = {}
  25 
  26      class << self
  27        # Adds a listener class.
  28        # Automatically called when a class inherits from Redmine::Hook::Listener.
  29        def add_listener(klass)
  30          raise "Hooks must include Singleton module." unless klass.included_modules.include?(Singleton)
  31          @@listener_classes << klass
  32          clear_listeners_instances
  33        end
  34 
  35        # Returns all the listerners instances.
  36        def listeners
  37          @@listeners ||= @@listener_classes.collect {|listener| listener.instance}
  38        end
  39 
  40        # Returns the listeners instances for the given hook.
  41        def hook_listeners(hook)
  42          @@hook_listeners[hook] ||= listeners.select {|listener| listener.respond_to?(hook)}
  43        end
  44 
  45        # Clears all the listeners.
  46        def clear_listeners
  47          @@listener_classes = []
  48          clear_listeners_instances
  49        end
  50 
  51        # Clears all the listeners instances.
  52        def clear_listeners_instances
  53          @@listeners = nil
  54          @@hook_listeners = {}
  55        end
  56 
  57        # Calls a hook.
  58        # Returns the listeners response.
  59        def call_hook(hook, context={})
  60          [].tap do |response|
  61            hls = hook_listeners(hook)
  62            if hls.any?
  63              hls.each {|listener| response << listener.send(hook, context)}
  64            end
  65          end
  66        end
  67      end
  68 
  69      # Base class for hook listeners.
  70      class Listener
  71        include Singleton
  72        include Redmine::I18n
  73 
  74        # Registers the listener
  75        def self.inherited(child)
  76          Redmine::Hook.add_listener(child)
  77          super
  78        end
  79 
  80      end
  81 
  82      # Listener class used for views hooks.
  83      # Listeners that inherit this class will include various helpers by default.
  84      class ViewListener < Listener
  85        include ERB::Util
  86        include ActionView::Helpers::TagHelper
  87        include ActionView::Helpers::FormHelper
  88        include ActionView::Helpers::FormTagHelper
  89        include ActionView::Helpers::FormOptionsHelper
  90        include ActionView::Helpers::JavaScriptHelper
  91        include ActionView::Helpers::PrototypeHelper
  92        include ActionView::Helpers::NumberHelper
  93        include ActionView::Helpers::UrlHelper
  94        include ActionView::Helpers::AssetTagHelper
  95        include ActionView::Helpers::TextHelper
  96        include ActionController::UrlWriter
  97        include ApplicationHelper
  98 
  99        # Default to creating links using only the path.  Subclasses can
 100        # change this default as needed
 101        def self.default_url_options
 102          {:only_path => true }
 103        end
 104 
 105        # Helper method to directly render a partial using the context:
 106        #
 107        #   class MyHook < Redmine::Hook::ViewListener
 108        #     render_on :view_issues_show_details_bottom, :partial => "show_more_data"
 109        #   end
 110        #
 111        def self.render_on(hook, options={})
 112          define_method hook do |context|
 113            context[:controller].send(:render_to_string, {:locals => context}.merge(options))
 114          end
 115        end
 116      end
 117 
 118      # Helper module included in ApplicationHelper and ActionController so that
 119      # hooks can be called in views like this:
 120      #
 121      #   <%= call_hook(:some_hook) %>
 122      #   <%= call_hook(:another_hook, :foo => 'bar') %>
 123      #
 124      # Or in controllers like:
 125      #   call_hook(:some_hook)
 126      #   call_hook(:another_hook, :foo => 'bar')
 127      #
 128      # Hooks added to views will be concatenated into a string. Hooks added to
 129      # controllers will return an array of results.
 130      #
 131      # Several objects are automatically added to the call context:
 132      #
 133      # * project => current project
 134      # * request => Request instance
 135      # * controller => current Controller instance
 136      #
 137      module Helper
 138        def call_hook(hook, context={})
 139          if is_a?(ActionController::Base)
 140            default_context = {:controller => self, :project => @project, :request => request}
 141            Redmine::Hook.call_hook(hook, default_context.merge(context))
 142          else
 143            default_context = { :project => @project }
 144            default_context[:controller] = controller if respond_to?(:controller)
 145            default_context[:request] = request if respond_to?(:request)
 146            Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ')
 147          end
 148        end
 149      end
 150    end
 151  end
 152 
 153  ApplicationHelper.send(:include, Redmine::Hook::Helper)
 154  ActionController::Base.send(:include, Redmine::Hook::Helper)