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