Revision 752
Added by Jean-Philippe Lang about 18 years ago
| trunk/app/controllers/admin_controller.rb | ||
|---|---|---|
| 74 | 74 |
:default_admin_changed => User.find(:first, :conditions => ["login=? and hashed_password=?", 'admin', User.hash_password('admin')]).nil?,
|
| 75 | 75 |
:file_repository_writable => File.writable?(Attachment.storage_path), |
| 76 | 76 |
:rmagick_available => Object.const_defined?(:Magick) |
| 77 |
} |
|
| 77 |
} |
|
| 78 |
@plugins = Redmine::Plugin.registered_plugins |
|
| 78 | 79 |
end |
| 79 | 80 |
end |
| trunk/app/controllers/settings_controller.rb | ||
|---|---|---|
| 30 | 30 |
redirect_to :action => 'edit' and return |
| 31 | 31 |
end |
| 32 | 32 |
end |
| 33 |
|
|
| 34 |
def plugin |
|
| 35 |
plugin_id = params[:id].to_sym |
|
| 36 |
@plugin = Redmine::Plugin.registered_plugins[plugin_id] |
|
| 37 |
if request.post? |
|
| 38 |
Setting["plugin_#{plugin_id}"] = params[:settings]
|
|
| 39 |
flash[:notice] = l(:notice_successful_update) |
|
| 40 |
redirect_to :action => 'plugin', :id => params[:id] |
|
| 41 |
end |
|
| 42 |
@partial = "../../vendor/plugins/#{plugin_id}/app/views/" + @plugin.settings[:partial]
|
|
| 43 |
@settings = Setting["plugin_#{plugin_id}"]
|
|
| 44 |
end |
|
| 33 | 45 |
end |
| trunk/app/models/setting.rb | ||
|---|---|---|
| 19 | 19 |
|
| 20 | 20 |
cattr_accessor :available_settings |
| 21 | 21 |
@@available_settings = YAML::load(File.open("#{RAILS_ROOT}/config/settings.yml"))
|
| 22 |
|
|
| 22 |
Redmine::Plugin.registered_plugins.each do |id, plugin| |
|
| 23 |
next unless plugin.settings |
|
| 24 |
@@available_settings["plugin_#{id}"] = {'default' => plugin.settings[:default], 'serialized' => true}
|
|
| 25 |
end |
|
| 26 |
|
|
| 23 | 27 |
validates_uniqueness_of :name |
| 24 | 28 |
validates_inclusion_of :name, :in => @@available_settings.keys |
| 25 | 29 |
validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }
|
| trunk/app/views/admin/info.rhtml | ||
|---|---|---|
| 7 | 7 |
<tr class="even"><td>File repository writable</td><td><%= image_tag (@flags[:file_repository_writable] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr> |
| 8 | 8 |
<tr class="odd"><td>RMagick available</td><td><%= image_tag (@flags[:rmagick_available] ? 'true.png' : 'false.png'), :style => "vertical-align:bottom;" %></td></tr> |
| 9 | 9 |
</table> |
| 10 |
|
|
| 11 |
<% if @plugins.any? %> |
|
| 12 |
|
|
| 13 |
<h3 class="icon22 icon22-plugin">Plugins</h3> |
|
| 14 |
<table class="list"> |
|
| 15 |
<% @plugins.keys.sort.each do |plugin| %> |
|
| 16 |
<tr class="<%= cycle('odd', 'even') %>">
|
|
| 17 |
<td><%=h @plugins[plugin].name %></td> |
|
| 18 |
<td><%=h @plugins[plugin].description %></td> |
|
| 19 |
<td><%=h @plugins[plugin].author %></td> |
|
| 20 |
<td><%=h @plugins[plugin].version %></td> |
|
| 21 |
<td><%= link_to('Configure', :controller => 'settings', :action => 'plugin', :id => plugin.to_s) if @plugins[plugin].configurable? %></td>
|
|
| 22 |
</tr> |
|
| 23 |
<% end %> |
|
| 24 |
</table> |
|
| 25 |
<% end %> |
|
| trunk/app/views/settings/plugin.rhtml | ||
|---|---|---|
| 1 |
<h2><%= l(:label_settings) %>: <%=h @plugin.name %></h2> |
|
| 2 |
|
|
| 3 |
<% form_tag({:action => 'plugin'}) do %>
|
|
| 4 |
<div class="box tabular"> |
|
| 5 |
<%= render :partial => @partial, :locals => {:settings => @settings}%>
|
|
| 6 |
</div> |
|
| 7 |
<%= submit_tag l(:button_apply) %> |
|
| 8 |
<% end %> |
|
| 0 | 9 | |
| trunk/config/environment.rb | ||
|---|---|---|
| 58 | 58 |
# ActionMailer::Base.deliveries array. |
| 59 | 59 |
#config.action_mailer.delivery_method = :test |
| 60 | 60 |
config.action_mailer.delivery_method = :smtp |
| 61 |
|
|
| 62 |
# Uncomment this line if the engines plugin is installed. |
|
| 63 |
# This will ensure that engines is loaded first. |
|
| 64 |
# config.plugins = ["engines", "*"] |
|
| 61 | 65 |
end |
| 62 | 66 |
|
| 63 | 67 |
ActiveRecord::Errors.default_error_messages = {
|
| trunk/lib/redmine/plugin.rb | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 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 #:nodoc: |
|
| 19 |
|
|
| 20 |
# Base class for Redmine plugins. |
|
| 21 |
# Plugins are registered using the <tt>register</tt> class method that acts as the public constructor. |
|
| 22 |
# |
|
| 23 |
# Redmine::Plugin.register :example do |
|
| 24 |
# name 'Example plugin' |
|
| 25 |
# author 'John Smith' |
|
| 26 |
# description 'This is an example plugin for Redmine' |
|
| 27 |
# version '0.0.1' |
|
| 28 |
# settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
|
|
| 29 |
# end |
|
| 30 |
# |
|
| 31 |
# === Plugin attributes |
|
| 32 |
# |
|
| 33 |
# +settings+ is an optional attribute that let the plugin be configurable. |
|
| 34 |
# It must be a hash with the following keys: |
|
| 35 |
# * <tt>:default</tt>: default value for the plugin settings |
|
| 36 |
# * <tt>:partial</tt>: path of the configuration partial view, relative to the plugin <tt>app/views</tt> directory |
|
| 37 |
# Example: |
|
| 38 |
# settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
|
|
| 39 |
# In this example, the settings partial will be found here in the plugin directory: <tt>app/views/settings/_settings.rhtml</tt>. |
|
| 40 |
# |
|
| 41 |
# When rendered, the plugin settings value is available as the local variable +settings+ |
|
| 42 |
class Plugin |
|
| 43 |
@registered_plugins = {}
|
|
| 44 |
class << self |
|
| 45 |
attr_reader :registered_plugins |
|
| 46 |
private :new |
|
| 47 |
|
|
| 48 |
def def_field(*names) |
|
| 49 |
class_eval do |
|
| 50 |
names.each do |name| |
|
| 51 |
define_method(name) do |*args| |
|
| 52 |
args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args)
|
|
| 53 |
end |
|
| 54 |
end |
|
| 55 |
end |
|
| 56 |
end |
|
| 57 |
end |
|
| 58 |
def_field :name, :description, :author, :version, :settings |
|
| 59 |
|
|
| 60 |
# Plugin constructor |
|
| 61 |
def self.register(name, &block) |
|
| 62 |
p = new |
|
| 63 |
p.instance_eval(&block) |
|
| 64 |
Plugin.registered_plugins[name] = p |
|
| 65 |
end |
|
| 66 |
|
|
| 67 |
# Adds an item to the given +menu+. |
|
| 68 |
# The +id+ parameter (equals to the project id) is automatically added to the url. |
|
| 69 |
# menu :project_menu, :label_plugin_example, :controller => 'example', :action => 'say_hello' |
|
| 70 |
# |
|
| 71 |
# Currently, only the project menu can be extended. Thus, the +name+ parameter must be +:project_menu+ |
|
| 72 |
def menu(name, label, url) |
|
| 73 |
Redmine::MenuManager.map(name) {|menu| menu.push label, url}
|
|
| 74 |
end |
|
| 75 |
|
|
| 76 |
# Defines a permission called +name+ for the given +actions+. |
|
| 77 |
# |
|
| 78 |
# The +actions+ argument is a hash with controllers as keys and actions as values (a single value or an array): |
|
| 79 |
# permission :destroy_contacts, { :contacts => :destroy }
|
|
| 80 |
# permission :view_contacts, { :contacts => [:index, :show] }
|
|
| 81 |
# |
|
| 82 |
# The +options+ argument can be used to make the permission public (implicitly given to any user) |
|
| 83 |
# or to restrict users the permission can be given to. |
|
| 84 |
# |
|
| 85 |
# Examples |
|
| 86 |
# # A permission that is implicitly given to any user |
|
| 87 |
# # This permission won't appear on the Roles & Permissions setup screen |
|
| 88 |
# permission :say_hello, { :example => :say_hello }, :public => true
|
|
| 89 |
# |
|
| 90 |
# # A permission that can be given to any user |
|
| 91 |
# permission :say_hello, { :example => :say_hello }
|
|
| 92 |
# |
|
| 93 |
# # A permission that can be given to registered users only |
|
| 94 |
# permission :say_hello, { :example => :say_hello }, :require => loggedin
|
|
| 95 |
# |
|
| 96 |
# # A permission that can be given to project members only |
|
| 97 |
# permission :say_hello, { :example => :say_hello }, :require => member
|
|
| 98 |
def permission(name, actions, options = {})
|
|
| 99 |
if @project_module |
|
| 100 |
Redmine::AccessControl.map {|map| map.project_module(@project_module) {|map|map.permission(name, actions, options)}}
|
|
| 101 |
else |
|
| 102 |
Redmine::AccessControl.map {|map| map.permission(name, actions, options)}
|
|
| 103 |
end |
|
| 104 |
end |
|
| 105 |
|
|
| 106 |
# Defines a project module, that can be enabled/disabled for each project. |
|
| 107 |
# Permissions defined inside +block+ will be bind to the module. |
|
| 108 |
# |
|
| 109 |
# project_module :things do |
|
| 110 |
# permission :view_contacts, { :contacts => [:list, :show] }, :public => true
|
|
| 111 |
# permission :destroy_contacts, { :contacts => :destroy }
|
|
| 112 |
# end |
|
| 113 |
def project_module(name, &block) |
|
| 114 |
@project_module = name |
|
| 115 |
self.instance_eval(&block) |
|
| 116 |
@project_module = nil |
|
| 117 |
end |
|
| 118 |
|
|
| 119 |
# Returns +true+ if the plugin can be configured. |
|
| 120 |
def configurable? |
|
| 121 |
settings && settings.is_a?(Hash) && !settings[:partial].blank? |
|
| 122 |
end |
|
| 123 |
end |
|
| 124 |
end |
|
| 0 | 125 | |
| trunk/lib/redmine.rb | ||
|---|---|---|
| 3 | 3 |
require 'redmine/mime_type' |
| 4 | 4 |
require 'redmine/acts_as_watchable/init' |
| 5 | 5 |
require 'redmine/acts_as_event/init' |
| 6 |
require 'redmine/plugin' |
|
| 6 | 7 |
|
| 7 | 8 |
begin |
| 8 | 9 |
require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick) |
| trunk/lib/tasks/migrate_plugins.rake | ||
|---|---|---|
| 1 |
namespace :db do |
|
| 2 |
desc 'Migrates installed plugins.' |
|
| 3 |
task :migrate_plugins => :environment do |
|
| 4 |
if Rails.respond_to?('plugins')
|
|
| 5 |
Rails.plugins.each do |plugin| |
|
| 6 |
next unless plugin.respond_to?('migrate')
|
|
| 7 |
puts "Migrating #{plugin.name}..."
|
|
| 8 |
plugin.migrate |
|
| 9 |
end |
|
| 10 |
else |
|
| 11 |
puts "Undefined method plugins for Rails!" |
|
| 12 |
puts "Make sure engines plugin is installed." |
|
| 13 |
end |
|
| 14 |
end |
|
| 15 |
end |
|
| trunk/public/stylesheets/application.css | ||
|---|---|---|
| 446 | 446 |
.icon22-comment { background-image: url(../images/22x22/comment.png); }
|
| 447 | 447 |
.icon22-package { background-image: url(../images/22x22/package.png); }
|
| 448 | 448 |
.icon22-settings { background-image: url(../images/22x22/settings.png); }
|
| 449 |
.icon22-plugin { background-image: url(../images/22x22/plugin.png); }
|
|
| trunk/vendor/plugins/gloc-1.1.0/lib/gloc-internal.rb | ||
|---|---|---|
| 73 | 73 |
end |
| 74 | 74 |
|
| 75 | 75 |
def _get_lang_file_list(dir) #:nodoc: |
| 76 |
dir= File.join(RAILS_ROOT,'lang') if dir.nil? |
|
| 76 |
dir= File.join(RAILS_ROOT,'{.,vendor/plugins/*}','lang') if dir.nil?
|
|
| 77 | 77 |
Dir[File.join(dir,'*.{yaml,yml}')]
|
| 78 | 78 |
end |
| 79 | 79 |
|
Also available in: Unified diff
Basic plugin support.