Commit 682ee5be54c21ad12f78597fca0e18a6f03af5d7
1 parent
99ae59ff
Exists in
master
and in
29 other branches
plugins: Support plugin to be defined as module instead of object
This makes possible for a plugin to be defined as module and have its main class defined inside it with the name Base (e.g. MyPlugin::Base). The advantages of this is to correctly scope plugins constants inside the module. There are many conflicts with the core if the plugin is defined as klass, for example: - if you define a MyPlugin::DisplayHelper you'll get the error 'warning: toplevel constant DisplayHelper referenced by MyPlugin::DisplayHelper' and your class won't be loaded unless you put a "require 'my_plugin/display_helper'" - `require` is also needed for contants with the sames of constants declared under Noosfero::Plugin. For example, if you define a MyPlugin::Manager or MyPlugin::Settings, Noosfero::Plugin::Manager or Noosfero::Plugin::Settings will be returned instead of your plugin's definition. - other hard to debug errors may also happen. This also encapsulates loading procedures into methods of Noosfero::Plugin.
Showing
4 changed files
with
76 additions
and
43 deletions
Show diff stats
lib/noosfero/plugin.rb
1 | require_dependency 'noosfero' | 1 | require_dependency 'noosfero' |
2 | +require 'noosfero/plugin/parent_methods' | ||
2 | 3 | ||
3 | class Noosfero::Plugin | 4 | class Noosfero::Plugin |
4 | 5 | ||
@@ -14,13 +15,9 @@ class Noosfero::Plugin | @@ -14,13 +15,9 @@ class Noosfero::Plugin | ||
14 | 15 | ||
15 | class << self | 16 | class << self |
16 | 17 | ||
17 | - attr_writer :should_load | 18 | + include Noosfero::Plugin::ParentMethods |
18 | 19 | ||
19 | - # Called for each ActiveRecord class with parents | ||
20 | - # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix | ||
21 | - def table_name_prefix | ||
22 | - @table_name_prefix ||= "#{name.to_s.underscore}_" | ||
23 | - end | 20 | + attr_writer :should_load |
24 | 21 | ||
25 | def should_load | 22 | def should_load |
26 | @should_load.nil? && true || @boot | 23 | @should_load.nil? && true || @boot |
@@ -92,8 +89,14 @@ class Noosfero::Plugin | @@ -92,8 +89,14 @@ class Noosfero::Plugin | ||
92 | end | 89 | end |
93 | end | 90 | end |
94 | 91 | ||
95 | - def load_plugin(plugin_name) | ||
96 | - (plugin_name.to_s.camelize + 'Plugin').constantize | 92 | + def load_plugin_identifier identifier |
93 | + klass = identifier.to_s.camelize.constantize | ||
94 | + klass = klass.const_get :Base if klass.class == Module | ||
95 | + klass | ||
96 | + end | ||
97 | + | ||
98 | + def load_plugin public_name | ||
99 | + load_plugin_identifier "#{public_name.to_s.camelize}Plugin" | ||
97 | end | 100 | end |
98 | 101 | ||
99 | # This is a generic method that initialize any possible filter defined by a | 102 | # This is a generic method that initialize any possible filter defined by a |
@@ -135,7 +138,7 @@ class Noosfero::Plugin | @@ -135,7 +138,7 @@ class Noosfero::Plugin | ||
135 | filters = [filters] | 138 | filters = [filters] |
136 | end | 139 | end |
137 | filters.each do |plugin_filter| | 140 | filters.each do |plugin_filter| |
138 | - filter_method = (plugin.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]).to_sym | 141 | + filter_method = "#{plugin.identifier}_#{plugin_filter[:method_name]}".to_sym |
139 | controller_class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {})) | 142 | controller_class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {})) |
140 | controller_class.send(:define_method, filter_method) do | 143 | controller_class.send(:define_method, filter_method) do |
141 | instance_exec(&plugin_filter[:block]) if environment.plugin_enabled?(plugin) | 144 | instance_exec(&plugin_filter[:block]) if environment.plugin_enabled?(plugin) |
@@ -168,38 +171,6 @@ class Noosfero::Plugin | @@ -168,38 +171,6 @@ class Noosfero::Plugin | ||
168 | @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize } | 171 | @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize } |
169 | end | 172 | end |
170 | 173 | ||
171 | - def public_name | ||
172 | - self.name.underscore.gsub('_plugin','') | ||
173 | - end | ||
174 | - | ||
175 | - def public_path file = '', relative=false | ||
176 | - File.join "#{if relative then '' else '/' end}plugins", public_name, file | ||
177 | - end | ||
178 | - | ||
179 | - def root_path | ||
180 | - Rails.root.join('plugins', public_name) | ||
181 | - end | ||
182 | - | ||
183 | - def view_path | ||
184 | - File.join(root_path,'views') | ||
185 | - end | ||
186 | - | ||
187 | - # Here the developer should specify the meta-informations that the plugin can | ||
188 | - # inform. | ||
189 | - def plugin_name | ||
190 | - self.name.underscore.humanize | ||
191 | - end | ||
192 | - def plugin_description | ||
193 | - _("No description informed.") | ||
194 | - end | ||
195 | - | ||
196 | - def admin_url | ||
197 | - {:controller => "#{name.underscore}_admin", :action => 'index'} | ||
198 | - end | ||
199 | - | ||
200 | - def has_admin_url? | ||
201 | - File.exists?(File.join(root_path, 'controllers', "#{name.underscore}_admin_controller.rb")) | ||
202 | - end | ||
203 | end | 174 | end |
204 | 175 | ||
205 | def expanded_template(file_path, locals = {}) | 176 | def expanded_template(file_path, locals = {}) |
lib/noosfero/plugin/manager.rb
@@ -76,7 +76,7 @@ class Noosfero::Plugin::Manager | @@ -76,7 +76,7 @@ class Noosfero::Plugin::Manager | ||
76 | 76 | ||
77 | def enabled_plugins | 77 | def enabled_plugins |
78 | @enabled_plugins ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin| | 78 | @enabled_plugins ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin| |
79 | - plugin.constantize.new(context) | 79 | + Noosfero::Plugin.load_plugin_identifier(plugin).new context |
80 | end | 80 | end |
81 | end | 81 | end |
82 | 82 |
@@ -0,0 +1,62 @@ | @@ -0,0 +1,62 @@ | ||
1 | +class Noosfero::Plugin | ||
2 | + | ||
3 | + # Plugins that are defined as modules should extend | ||
4 | + # this module manually, for example: | ||
5 | + # module MyPlugin | ||
6 | + # extend Noosfero::Plugin::ParentMethods | ||
7 | + # end | ||
8 | + module ParentMethods | ||
9 | + | ||
10 | + def identifier | ||
11 | + @identifier ||= (if self.parents.first.instance_of? Module then self.parents.first else self end).name.underscore | ||
12 | + end | ||
13 | + | ||
14 | + def public_name | ||
15 | + @public_name ||= self.identifier.gsub '_plugin', '' | ||
16 | + end | ||
17 | + | ||
18 | + # Here the developer should specify the meta-informations that the plugin can | ||
19 | + # inform. | ||
20 | + def plugin_name | ||
21 | + self.identifier.humanize | ||
22 | + end | ||
23 | + def plugin_description | ||
24 | + _("No description informed.") | ||
25 | + end | ||
26 | + | ||
27 | + # Called for each ActiveRecord model with parents | ||
28 | + # See http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/full_table_name_prefix | ||
29 | + def table_name_prefix | ||
30 | + @table_name_prefix ||= "#{self.identifier}_" | ||
31 | + end | ||
32 | + | ||
33 | + def public_path file = '', relative=false | ||
34 | + File.join "#{if relative then '' else '/' end}plugins", public_name, file | ||
35 | + end | ||
36 | + | ||
37 | + def root_path | ||
38 | + Rails.root.join('plugins', public_name) | ||
39 | + end | ||
40 | + | ||
41 | + def view_path | ||
42 | + File.join(root_path,'views') | ||
43 | + end | ||
44 | + | ||
45 | + def admin_url | ||
46 | + {:controller => "#{self.identifier}_admin", :action => 'index'} | ||
47 | + end | ||
48 | + | ||
49 | + def has_admin_url? | ||
50 | + File.exists?(File.join(root_path, 'controllers', "#{self.identifier}_admin_controller.rb")) | ||
51 | + end | ||
52 | + | ||
53 | + def controllers | ||
54 | + @controllers ||= Dir.glob("#{self.root_path}/controllers/*/*").map do |controller_file| | ||
55 | + next unless controller_file =~ /_controller.rb$/ | ||
56 | + controller = File.basename(controller_file).gsub(/.rb$/, '').camelize | ||
57 | + end.compact | ||
58 | + end | ||
59 | + | ||
60 | + end | ||
61 | + | ||
62 | +end |
test/unit/plugin_test.rb
@@ -23,7 +23,7 @@ class PluginTest < ActiveSupport::TestCase | @@ -23,7 +23,7 @@ class PluginTest < ActiveSupport::TestCase | ||
23 | end | 23 | end |
24 | 24 | ||
25 | should 'returns empty hash for class method extra_blocks by default if no blocks are defined on plugin' do | 25 | should 'returns empty hash for class method extra_blocks by default if no blocks are defined on plugin' do |
26 | - | 26 | + |
27 | class SomePlugin1 < Noosfero::Plugin | 27 | class SomePlugin1 < Noosfero::Plugin |
28 | end | 28 | end |
29 | 29 |