@@ -1,86 +1,86 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2011 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2011 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 | class AdminController < ApplicationController |
|
18 | class AdminController < ApplicationController | |
19 | layout 'admin' |
|
19 | layout 'admin' | |
20 | menu_item :projects, :only => :projects |
|
20 | menu_item :projects, :only => :projects | |
21 | menu_item :plugins, :only => :plugins |
|
21 | menu_item :plugins, :only => :plugins | |
22 | menu_item :info, :only => :info |
|
22 | menu_item :info, :only => :info | |
23 |
|
23 | |||
24 | before_filter :require_admin |
|
24 | before_filter :require_admin | |
25 | helper :sort |
|
25 | helper :sort | |
26 | include SortHelper |
|
26 | include SortHelper | |
27 |
|
27 | |||
28 | def index |
|
28 | def index | |
29 | @no_configuration_data = Redmine::DefaultData::Loader::no_data? |
|
29 | @no_configuration_data = Redmine::DefaultData::Loader::no_data? | |
30 | end |
|
30 | end | |
31 |
|
31 | |||
32 | def projects |
|
32 | def projects | |
33 | @status = params[:status] || 1 |
|
33 | @status = params[:status] || 1 | |
34 |
|
34 | |||
35 | scope = Project.status(@status) |
|
35 | scope = Project.status(@status) | |
36 | scope = scope.like(params[:name]) if params[:name].present? |
|
36 | scope = scope.like(params[:name]) if params[:name].present? | |
37 |
|
37 | |||
38 | @projects = scope.all(:order => 'lft') |
|
38 | @projects = scope.all(:order => 'lft') | |
39 |
|
39 | |||
40 | render :action => "projects", :layout => false if request.xhr? |
|
40 | render :action => "projects", :layout => false if request.xhr? | |
41 | end |
|
41 | end | |
42 |
|
42 | |||
43 | def plugins |
|
43 | def plugins | |
44 | @plugins = Redmine::Plugin.all |
|
44 | @plugins = Redmine::Plugin.all | |
45 | end |
|
45 | end | |
46 |
|
46 | |||
47 | # Loads the default configuration |
|
47 | # Loads the default configuration | |
48 | # (roles, trackers, statuses, workflow, enumerations) |
|
48 | # (roles, trackers, statuses, workflow, enumerations) | |
49 | def default_configuration |
|
49 | def default_configuration | |
50 | if request.post? |
|
50 | if request.post? | |
51 | begin |
|
51 | begin | |
52 | Redmine::DefaultData::Loader::load(params[:lang]) |
|
52 | Redmine::DefaultData::Loader::load(params[:lang]) | |
53 | flash[:notice] = l(:notice_default_data_loaded) |
|
53 | flash[:notice] = l(:notice_default_data_loaded) | |
54 | rescue Exception => e |
|
54 | rescue Exception => e | |
55 | flash[:error] = l(:error_can_t_load_default_data, e.message) |
|
55 | flash[:error] = l(:error_can_t_load_default_data, e.message) | |
56 | end |
|
56 | end | |
57 | end |
|
57 | end | |
58 | redirect_to :action => 'index' |
|
58 | redirect_to :action => 'index' | |
59 | end |
|
59 | end | |
60 |
|
60 | |||
61 | def test_email |
|
61 | def test_email | |
62 | raise_delivery_errors = ActionMailer::Base.raise_delivery_errors |
|
62 | raise_delivery_errors = ActionMailer::Base.raise_delivery_errors | |
63 | # Force ActionMailer to raise delivery errors so we can catch it |
|
63 | # Force ActionMailer to raise delivery errors so we can catch it | |
64 | ActionMailer::Base.raise_delivery_errors = true |
|
64 | ActionMailer::Base.raise_delivery_errors = true | |
65 | begin |
|
65 | begin | |
66 | @test = Mailer.deliver_test(User.current) |
|
66 | @test = Mailer.deliver_test(User.current) | |
67 | flash[:notice] = l(:notice_email_sent, User.current.mail) |
|
67 | flash[:notice] = l(:notice_email_sent, User.current.mail) | |
68 | rescue Exception => e |
|
68 | rescue Exception => e | |
69 | flash[:error] = l(:notice_email_error, e.message) |
|
69 | flash[:error] = l(:notice_email_error, e.message) | |
70 | end |
|
70 | end | |
71 | ActionMailer::Base.raise_delivery_errors = raise_delivery_errors |
|
71 | ActionMailer::Base.raise_delivery_errors = raise_delivery_errors | |
72 | redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications' |
|
72 | redirect_to :controller => 'settings', :action => 'edit', :tab => 'notifications' | |
73 | end |
|
73 | end | |
74 |
|
74 | |||
75 | def info |
|
75 | def info | |
76 | @db_adapter_name = ActiveRecord::Base.connection.adapter_name |
|
76 | @db_adapter_name = ActiveRecord::Base.connection.adapter_name | |
77 | @checklist = [ |
|
77 | @checklist = [ | |
78 | [:text_default_administrator_account_changed, |
|
78 | [:text_default_administrator_account_changed, | |
79 | User.find(:first, |
|
79 | User.find(:first, | |
80 | :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?], |
|
80 | :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?], | |
81 | [:text_file_repository_writable, File.writable?(Attachment.storage_path)], |
|
81 | [:text_file_repository_writable, File.writable?(Attachment.storage_path)], | |
82 |
[:text_plugin_assets_writable, File.writable?( |
|
82 | [:text_plugin_assets_writable, File.writable?(Redmine::Plugin.public_directory)], | |
83 | [:text_rmagick_available, Object.const_defined?(:Magick)] |
|
83 | [:text_rmagick_available, Object.const_defined?(:Magick)] | |
84 | ] |
|
84 | ] | |
85 | end |
|
85 | end | |
86 | end |
|
86 | end |
@@ -1,278 +1,281 | |||||
1 | # Redmine - project management software |
|
1 | # Redmine - project management software | |
2 | # Copyright (C) 2006-2011 Jean-Philippe Lang |
|
2 | # Copyright (C) 2006-2011 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 #:nodoc: |
|
18 | module Redmine #:nodoc: | |
19 |
|
19 | |||
20 | class PluginNotFound < StandardError; end |
|
20 | class PluginNotFound < StandardError; end | |
21 | class PluginRequirementError < StandardError; end |
|
21 | class PluginRequirementError < StandardError; end | |
22 |
|
22 | |||
23 | # Base class for Redmine plugins. |
|
23 | # Base class for Redmine plugins. | |
24 | # Plugins are registered using the <tt>register</tt> class method that acts as the public constructor. |
|
24 | # Plugins are registered using the <tt>register</tt> class method that acts as the public constructor. | |
25 | # |
|
25 | # | |
26 | # Redmine::Plugin.register :example do |
|
26 | # Redmine::Plugin.register :example do | |
27 | # name 'Example plugin' |
|
27 | # name 'Example plugin' | |
28 | # author 'John Smith' |
|
28 | # author 'John Smith' | |
29 | # description 'This is an example plugin for Redmine' |
|
29 | # description 'This is an example plugin for Redmine' | |
30 | # version '0.0.1' |
|
30 | # version '0.0.1' | |
31 | # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings' |
|
31 | # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings' | |
32 | # end |
|
32 | # end | |
33 | # |
|
33 | # | |
34 | # === Plugin attributes |
|
34 | # === Plugin attributes | |
35 | # |
|
35 | # | |
36 | # +settings+ is an optional attribute that let the plugin be configurable. |
|
36 | # +settings+ is an optional attribute that let the plugin be configurable. | |
37 | # It must be a hash with the following keys: |
|
37 | # It must be a hash with the following keys: | |
38 | # * <tt>:default</tt>: default value for the plugin settings |
|
38 | # * <tt>:default</tt>: default value for the plugin settings | |
39 | # * <tt>:partial</tt>: path of the configuration partial view, relative to the plugin <tt>app/views</tt> directory |
|
39 | # * <tt>:partial</tt>: path of the configuration partial view, relative to the plugin <tt>app/views</tt> directory | |
40 | # Example: |
|
40 | # Example: | |
41 | # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings' |
|
41 | # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings' | |
42 | # In this example, the settings partial will be found here in the plugin directory: <tt>app/views/settings/_settings.rhtml</tt>. |
|
42 | # In this example, the settings partial will be found here in the plugin directory: <tt>app/views/settings/_settings.rhtml</tt>. | |
43 | # |
|
43 | # | |
44 | # When rendered, the plugin settings value is available as the local variable +settings+ |
|
44 | # When rendered, the plugin settings value is available as the local variable +settings+ | |
45 | class Plugin |
|
45 | class Plugin | |
|
46 | cattr_accessor :public_directory | |||
|
47 | self.public_directory = File.join(Rails.root, 'public', 'plugin_assets') | |||
|
48 | ||||
46 | @registered_plugins = {} |
|
49 | @registered_plugins = {} | |
47 | class << self |
|
50 | class << self | |
48 | attr_reader :registered_plugins |
|
51 | attr_reader :registered_plugins | |
49 | private :new |
|
52 | private :new | |
50 |
|
53 | |||
51 | def def_field(*names) |
|
54 | def def_field(*names) | |
52 | class_eval do |
|
55 | class_eval do | |
53 | names.each do |name| |
|
56 | names.each do |name| | |
54 | define_method(name) do |*args| |
|
57 | define_method(name) do |*args| | |
55 | args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args) |
|
58 | args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args) | |
56 | end |
|
59 | end | |
57 | end |
|
60 | end | |
58 | end |
|
61 | end | |
59 | end |
|
62 | end | |
60 | end |
|
63 | end | |
61 | def_field :name, :description, :url, :author, :author_url, :version, :settings |
|
64 | def_field :name, :description, :url, :author, :author_url, :version, :settings | |
62 | attr_reader :id |
|
65 | attr_reader :id | |
63 |
|
66 | |||
64 | # Plugin constructor |
|
67 | # Plugin constructor | |
65 | def self.register(id, &block) |
|
68 | def self.register(id, &block) | |
66 | p = new(id) |
|
69 | p = new(id) | |
67 | p.instance_eval(&block) |
|
70 | p.instance_eval(&block) | |
68 | # Set a default name if it was not provided during registration |
|
71 | # Set a default name if it was not provided during registration | |
69 | p.name(id.to_s.humanize) if p.name.nil? |
|
72 | p.name(id.to_s.humanize) if p.name.nil? | |
70 | # Adds plugin locales if any |
|
73 | # Adds plugin locales if any | |
71 | # YAML translation files should be found under <plugin>/config/locales/ |
|
74 | # YAML translation files should be found under <plugin>/config/locales/ | |
72 | ::I18n.load_path += Dir.glob(File.join(Rails.root, 'vendor', 'plugins', id.to_s, 'config', 'locales', '*.yml')) |
|
75 | ::I18n.load_path += Dir.glob(File.join(Rails.root, 'vendor', 'plugins', id.to_s, 'config', 'locales', '*.yml')) | |
73 | registered_plugins[id] = p |
|
76 | registered_plugins[id] = p | |
74 | end |
|
77 | end | |
75 |
|
78 | |||
76 | # Returns an array of all registered plugins |
|
79 | # Returns an array of all registered plugins | |
77 | def self.all |
|
80 | def self.all | |
78 | registered_plugins.values.sort |
|
81 | registered_plugins.values.sort | |
79 | end |
|
82 | end | |
80 |
|
83 | |||
81 | # Finds a plugin by its id |
|
84 | # Finds a plugin by its id | |
82 | # Returns a PluginNotFound exception if the plugin doesn't exist |
|
85 | # Returns a PluginNotFound exception if the plugin doesn't exist | |
83 | def self.find(id) |
|
86 | def self.find(id) | |
84 | registered_plugins[id.to_sym] || raise(PluginNotFound) |
|
87 | registered_plugins[id.to_sym] || raise(PluginNotFound) | |
85 | end |
|
88 | end | |
86 |
|
89 | |||
87 | # Clears the registered plugins hash |
|
90 | # Clears the registered plugins hash | |
88 | # It doesn't unload installed plugins |
|
91 | # It doesn't unload installed plugins | |
89 | def self.clear |
|
92 | def self.clear | |
90 | @registered_plugins = {} |
|
93 | @registered_plugins = {} | |
91 | end |
|
94 | end | |
92 |
|
95 | |||
93 | # Checks if a plugin is installed |
|
96 | # Checks if a plugin is installed | |
94 | # |
|
97 | # | |
95 | # @param [String] id name of the plugin |
|
98 | # @param [String] id name of the plugin | |
96 | def self.installed?(id) |
|
99 | def self.installed?(id) | |
97 | registered_plugins[id.to_sym].present? |
|
100 | registered_plugins[id.to_sym].present? | |
98 | end |
|
101 | end | |
99 |
|
102 | |||
100 | def initialize(id) |
|
103 | def initialize(id) | |
101 | @id = id.to_sym |
|
104 | @id = id.to_sym | |
102 | end |
|
105 | end | |
103 |
|
106 | |||
104 | def <=>(plugin) |
|
107 | def <=>(plugin) | |
105 | self.id.to_s <=> plugin.id.to_s |
|
108 | self.id.to_s <=> plugin.id.to_s | |
106 | end |
|
109 | end | |
107 |
|
110 | |||
108 | # Sets a requirement on Redmine version |
|
111 | # Sets a requirement on Redmine version | |
109 | # Raises a PluginRequirementError exception if the requirement is not met |
|
112 | # Raises a PluginRequirementError exception if the requirement is not met | |
110 | # |
|
113 | # | |
111 | # Examples |
|
114 | # Examples | |
112 | # # Requires Redmine 0.7.3 or higher |
|
115 | # # Requires Redmine 0.7.3 or higher | |
113 | # requires_redmine :version_or_higher => '0.7.3' |
|
116 | # requires_redmine :version_or_higher => '0.7.3' | |
114 | # requires_redmine '0.7.3' |
|
117 | # requires_redmine '0.7.3' | |
115 | # |
|
118 | # | |
116 | # # Requires a specific Redmine version |
|
119 | # # Requires a specific Redmine version | |
117 | # requires_redmine :version => '0.7.3' # 0.7.3 only |
|
120 | # requires_redmine :version => '0.7.3' # 0.7.3 only | |
118 | # requires_redmine :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0 |
|
121 | # requires_redmine :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0 | |
119 | def requires_redmine(arg) |
|
122 | def requires_redmine(arg) | |
120 | arg = { :version_or_higher => arg } unless arg.is_a?(Hash) |
|
123 | arg = { :version_or_higher => arg } unless arg.is_a?(Hash) | |
121 | arg.assert_valid_keys(:version, :version_or_higher) |
|
124 | arg.assert_valid_keys(:version, :version_or_higher) | |
122 |
|
125 | |||
123 | current = Redmine::VERSION.to_a |
|
126 | current = Redmine::VERSION.to_a | |
124 | arg.each do |k, v| |
|
127 | arg.each do |k, v| | |
125 | v = [] << v unless v.is_a?(Array) |
|
128 | v = [] << v unless v.is_a?(Array) | |
126 | versions = v.collect {|s| s.split('.').collect(&:to_i)} |
|
129 | versions = v.collect {|s| s.split('.').collect(&:to_i)} | |
127 | case k |
|
130 | case k | |
128 | when :version_or_higher |
|
131 | when :version_or_higher | |
129 | raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1 |
|
132 | raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1 | |
130 | unless (current <=> versions.first) >= 0 |
|
133 | unless (current <=> versions.first) >= 0 | |
131 | raise PluginRequirementError.new("#{id} plugin requires Redmine #{v} or higher but current is #{current.join('.')}") |
|
134 | raise PluginRequirementError.new("#{id} plugin requires Redmine #{v} or higher but current is #{current.join('.')}") | |
132 | end |
|
135 | end | |
133 | when :version |
|
136 | when :version | |
134 | unless versions.include?(current.slice(0,3)) |
|
137 | unless versions.include?(current.slice(0,3)) | |
135 | raise PluginRequirementError.new("#{id} plugin requires one the following Redmine versions: #{v.join(', ')} but current is #{current.join('.')}") |
|
138 | raise PluginRequirementError.new("#{id} plugin requires one the following Redmine versions: #{v.join(', ')} but current is #{current.join('.')}") | |
136 | end |
|
139 | end | |
137 | end |
|
140 | end | |
138 | end |
|
141 | end | |
139 | true |
|
142 | true | |
140 | end |
|
143 | end | |
141 |
|
144 | |||
142 | # Sets a requirement on a Redmine plugin version |
|
145 | # Sets a requirement on a Redmine plugin version | |
143 | # Raises a PluginRequirementError exception if the requirement is not met |
|
146 | # Raises a PluginRequirementError exception if the requirement is not met | |
144 | # |
|
147 | # | |
145 | # Examples |
|
148 | # Examples | |
146 | # # Requires a plugin named :foo version 0.7.3 or higher |
|
149 | # # Requires a plugin named :foo version 0.7.3 or higher | |
147 | # requires_redmine_plugin :foo, :version_or_higher => '0.7.3' |
|
150 | # requires_redmine_plugin :foo, :version_or_higher => '0.7.3' | |
148 | # requires_redmine_plugin :foo, '0.7.3' |
|
151 | # requires_redmine_plugin :foo, '0.7.3' | |
149 | # |
|
152 | # | |
150 | # # Requires a specific version of a Redmine plugin |
|
153 | # # Requires a specific version of a Redmine plugin | |
151 | # requires_redmine_plugin :foo, :version => '0.7.3' # 0.7.3 only |
|
154 | # requires_redmine_plugin :foo, :version => '0.7.3' # 0.7.3 only | |
152 | # requires_redmine_plugin :foo, :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0 |
|
155 | # requires_redmine_plugin :foo, :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0 | |
153 | def requires_redmine_plugin(plugin_name, arg) |
|
156 | def requires_redmine_plugin(plugin_name, arg) | |
154 | arg = { :version_or_higher => arg } unless arg.is_a?(Hash) |
|
157 | arg = { :version_or_higher => arg } unless arg.is_a?(Hash) | |
155 | arg.assert_valid_keys(:version, :version_or_higher) |
|
158 | arg.assert_valid_keys(:version, :version_or_higher) | |
156 |
|
159 | |||
157 | plugin = Plugin.find(plugin_name) |
|
160 | plugin = Plugin.find(plugin_name) | |
158 | current = plugin.version.split('.').collect(&:to_i) |
|
161 | current = plugin.version.split('.').collect(&:to_i) | |
159 |
|
162 | |||
160 | arg.each do |k, v| |
|
163 | arg.each do |k, v| | |
161 | v = [] << v unless v.is_a?(Array) |
|
164 | v = [] << v unless v.is_a?(Array) | |
162 | versions = v.collect {|s| s.split('.').collect(&:to_i)} |
|
165 | versions = v.collect {|s| s.split('.').collect(&:to_i)} | |
163 | case k |
|
166 | case k | |
164 | when :version_or_higher |
|
167 | when :version_or_higher | |
165 | raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1 |
|
168 | raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1 | |
166 | unless (current <=> versions.first) >= 0 |
|
169 | unless (current <=> versions.first) >= 0 | |
167 | raise PluginRequirementError.new("#{id} plugin requires the #{plugin_name} plugin #{v} or higher but current is #{current.join('.')}") |
|
170 | raise PluginRequirementError.new("#{id} plugin requires the #{plugin_name} plugin #{v} or higher but current is #{current.join('.')}") | |
168 | end |
|
171 | end | |
169 | when :version |
|
172 | when :version | |
170 | unless versions.include?(current.slice(0,3)) |
|
173 | unless versions.include?(current.slice(0,3)) | |
171 | raise PluginRequirementError.new("#{id} plugin requires one the following versions of #{plugin_name}: #{v.join(', ')} but current is #{current.join('.')}") |
|
174 | raise PluginRequirementError.new("#{id} plugin requires one the following versions of #{plugin_name}: #{v.join(', ')} but current is #{current.join('.')}") | |
172 | end |
|
175 | end | |
173 | end |
|
176 | end | |
174 | end |
|
177 | end | |
175 | true |
|
178 | true | |
176 | end |
|
179 | end | |
177 |
|
180 | |||
178 | # Adds an item to the given +menu+. |
|
181 | # Adds an item to the given +menu+. | |
179 | # The +id+ parameter (equals to the project id) is automatically added to the url. |
|
182 | # The +id+ parameter (equals to the project id) is automatically added to the url. | |
180 | # menu :project_menu, :plugin_example, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample' |
|
183 | # menu :project_menu, :plugin_example, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample' | |
181 | # |
|
184 | # | |
182 | # +name+ parameter can be: :top_menu, :account_menu, :application_menu or :project_menu |
|
185 | # +name+ parameter can be: :top_menu, :account_menu, :application_menu or :project_menu | |
183 | # |
|
186 | # | |
184 | def menu(menu, item, url, options={}) |
|
187 | def menu(menu, item, url, options={}) | |
185 | Redmine::MenuManager.map(menu).push(item, url, options) |
|
188 | Redmine::MenuManager.map(menu).push(item, url, options) | |
186 | end |
|
189 | end | |
187 | alias :add_menu_item :menu |
|
190 | alias :add_menu_item :menu | |
188 |
|
191 | |||
189 | # Removes +item+ from the given +menu+. |
|
192 | # Removes +item+ from the given +menu+. | |
190 | def delete_menu_item(menu, item) |
|
193 | def delete_menu_item(menu, item) | |
191 | Redmine::MenuManager.map(menu).delete(item) |
|
194 | Redmine::MenuManager.map(menu).delete(item) | |
192 | end |
|
195 | end | |
193 |
|
196 | |||
194 | # Defines a permission called +name+ for the given +actions+. |
|
197 | # Defines a permission called +name+ for the given +actions+. | |
195 | # |
|
198 | # | |
196 | # The +actions+ argument is a hash with controllers as keys and actions as values (a single value or an array): |
|
199 | # The +actions+ argument is a hash with controllers as keys and actions as values (a single value or an array): | |
197 | # permission :destroy_contacts, { :contacts => :destroy } |
|
200 | # permission :destroy_contacts, { :contacts => :destroy } | |
198 | # permission :view_contacts, { :contacts => [:index, :show] } |
|
201 | # permission :view_contacts, { :contacts => [:index, :show] } | |
199 | # |
|
202 | # | |
200 | # The +options+ argument can be used to make the permission public (implicitly given to any user) |
|
203 | # The +options+ argument can be used to make the permission public (implicitly given to any user) | |
201 | # or to restrict users the permission can be given to. |
|
204 | # or to restrict users the permission can be given to. | |
202 | # |
|
205 | # | |
203 | # Examples |
|
206 | # Examples | |
204 | # # A permission that is implicitly given to any user |
|
207 | # # A permission that is implicitly given to any user | |
205 | # # This permission won't appear on the Roles & Permissions setup screen |
|
208 | # # This permission won't appear on the Roles & Permissions setup screen | |
206 | # permission :say_hello, { :example => :say_hello }, :public => true |
|
209 | # permission :say_hello, { :example => :say_hello }, :public => true | |
207 | # |
|
210 | # | |
208 | # # A permission that can be given to any user |
|
211 | # # A permission that can be given to any user | |
209 | # permission :say_hello, { :example => :say_hello } |
|
212 | # permission :say_hello, { :example => :say_hello } | |
210 | # |
|
213 | # | |
211 | # # A permission that can be given to registered users only |
|
214 | # # A permission that can be given to registered users only | |
212 | # permission :say_hello, { :example => :say_hello }, :require => :loggedin |
|
215 | # permission :say_hello, { :example => :say_hello }, :require => :loggedin | |
213 | # |
|
216 | # | |
214 | # # A permission that can be given to project members only |
|
217 | # # A permission that can be given to project members only | |
215 | # permission :say_hello, { :example => :say_hello }, :require => :member |
|
218 | # permission :say_hello, { :example => :say_hello }, :require => :member | |
216 | def permission(name, actions, options = {}) |
|
219 | def permission(name, actions, options = {}) | |
217 | if @project_module |
|
220 | if @project_module | |
218 | Redmine::AccessControl.map {|map| map.project_module(@project_module) {|map|map.permission(name, actions, options)}} |
|
221 | Redmine::AccessControl.map {|map| map.project_module(@project_module) {|map|map.permission(name, actions, options)}} | |
219 | else |
|
222 | else | |
220 | Redmine::AccessControl.map {|map| map.permission(name, actions, options)} |
|
223 | Redmine::AccessControl.map {|map| map.permission(name, actions, options)} | |
221 | end |
|
224 | end | |
222 | end |
|
225 | end | |
223 |
|
226 | |||
224 | # Defines a project module, that can be enabled/disabled for each project. |
|
227 | # Defines a project module, that can be enabled/disabled for each project. | |
225 | # Permissions defined inside +block+ will be bind to the module. |
|
228 | # Permissions defined inside +block+ will be bind to the module. | |
226 | # |
|
229 | # | |
227 | # project_module :things do |
|
230 | # project_module :things do | |
228 | # permission :view_contacts, { :contacts => [:list, :show] }, :public => true |
|
231 | # permission :view_contacts, { :contacts => [:list, :show] }, :public => true | |
229 | # permission :destroy_contacts, { :contacts => :destroy } |
|
232 | # permission :destroy_contacts, { :contacts => :destroy } | |
230 | # end |
|
233 | # end | |
231 | def project_module(name, &block) |
|
234 | def project_module(name, &block) | |
232 | @project_module = name |
|
235 | @project_module = name | |
233 | self.instance_eval(&block) |
|
236 | self.instance_eval(&block) | |
234 | @project_module = nil |
|
237 | @project_module = nil | |
235 | end |
|
238 | end | |
236 |
|
239 | |||
237 | # Registers an activity provider. |
|
240 | # Registers an activity provider. | |
238 | # |
|
241 | # | |
239 | # Options: |
|
242 | # Options: | |
240 | # * <tt>:class_name</tt> - one or more model(s) that provide these events (inferred from event_type by default) |
|
243 | # * <tt>:class_name</tt> - one or more model(s) that provide these events (inferred from event_type by default) | |
241 | # * <tt>:default</tt> - setting this option to false will make the events not displayed by default |
|
244 | # * <tt>:default</tt> - setting this option to false will make the events not displayed by default | |
242 | # |
|
245 | # | |
243 | # A model can provide several activity event types. |
|
246 | # A model can provide several activity event types. | |
244 | # |
|
247 | # | |
245 | # Examples: |
|
248 | # Examples: | |
246 | # register :news |
|
249 | # register :news | |
247 | # register :scrums, :class_name => 'Meeting' |
|
250 | # register :scrums, :class_name => 'Meeting' | |
248 | # register :issues, :class_name => ['Issue', 'Journal'] |
|
251 | # register :issues, :class_name => ['Issue', 'Journal'] | |
249 | # |
|
252 | # | |
250 | # Retrieving events: |
|
253 | # Retrieving events: | |
251 | # Associated model(s) must implement the find_events class method. |
|
254 | # Associated model(s) must implement the find_events class method. | |
252 | # ActiveRecord models can use acts_as_activity_provider as a way to implement this class method. |
|
255 | # ActiveRecord models can use acts_as_activity_provider as a way to implement this class method. | |
253 | # |
|
256 | # | |
254 | # The following call should return all the scrum events visible by current user that occured in the 5 last days: |
|
257 | # The following call should return all the scrum events visible by current user that occured in the 5 last days: | |
255 | # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today) |
|
258 | # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today) | |
256 | # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only |
|
259 | # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only | |
257 | # |
|
260 | # | |
258 | # Note that :view_scrums permission is required to view these events in the activity view. |
|
261 | # Note that :view_scrums permission is required to view these events in the activity view. | |
259 | def activity_provider(*args) |
|
262 | def activity_provider(*args) | |
260 | Redmine::Activity.register(*args) |
|
263 | Redmine::Activity.register(*args) | |
261 | end |
|
264 | end | |
262 |
|
265 | |||
263 | # Registers a wiki formatter. |
|
266 | # Registers a wiki formatter. | |
264 | # |
|
267 | # | |
265 | # Parameters: |
|
268 | # Parameters: | |
266 | # * +name+ - human-readable name |
|
269 | # * +name+ - human-readable name | |
267 | # * +formatter+ - formatter class, which should have an instance method +to_html+ |
|
270 | # * +formatter+ - formatter class, which should have an instance method +to_html+ | |
268 | # * +helper+ - helper module, which will be included by wiki pages |
|
271 | # * +helper+ - helper module, which will be included by wiki pages | |
269 | def wiki_format_provider(name, formatter, helper) |
|
272 | def wiki_format_provider(name, formatter, helper) | |
270 | Redmine::WikiFormatting.register(name, formatter, helper) |
|
273 | Redmine::WikiFormatting.register(name, formatter, helper) | |
271 | end |
|
274 | end | |
272 |
|
275 | |||
273 | # Returns +true+ if the plugin can be configured. |
|
276 | # Returns +true+ if the plugin can be configured. | |
274 | def configurable? |
|
277 | def configurable? | |
275 | settings && settings.is_a?(Hash) && !settings[:partial].blank? |
|
278 | settings && settings.is_a?(Hash) && !settings[:partial].blank? | |
276 | end |
|
279 | end | |
277 | end |
|
280 | end | |
278 | end |
|
281 | end |
General Comments 0
You need to be logged in to leave comments.
Login now