Commit cbac61f7f0457ee547bb321989013a25b973efe2
Exists in
master
and in
22 other branches
Merge branch 'master' into antispam
Conflicts: lib/noosfero/plugin/context.rb lib/noosfero/plugin/manager.rb test/unit/plugin_manager_test.rb
Showing
38 changed files
with
1112 additions
and
47 deletions
Show diff stats
app/controllers/application_controller.rb
1 | class ApplicationController < ActionController::Base | 1 | class ApplicationController < ActionController::Base |
2 | 2 | ||
3 | before_filter :setup_multitenancy | 3 | before_filter :setup_multitenancy |
4 | + before_filter :detect_stuff_by_domain | ||
5 | + before_filter :init_noosfero_plugins | ||
4 | 6 | ||
5 | include ApplicationHelper | 7 | include ApplicationHelper |
6 | layout :get_layout | 8 | layout :get_layout |
@@ -51,8 +53,6 @@ class ApplicationController < ActionController::Base | @@ -51,8 +53,6 @@ class ApplicationController < ActionController::Base | ||
51 | 53 | ||
52 | include NeedsProfile | 54 | include NeedsProfile |
53 | 55 | ||
54 | - before_filter :detect_stuff_by_domain | ||
55 | - before_filter :init_noosfero_plugins | ||
56 | attr_reader :environment | 56 | attr_reader :environment |
57 | 57 | ||
58 | before_filter :load_terminology | 58 | before_filter :load_terminology |
app/helpers/application_helper.rb
@@ -1352,4 +1352,53 @@ module ApplicationHelper | @@ -1352,4 +1352,53 @@ module ApplicationHelper | ||
1352 | :style => 'margin-top: 1em' | 1352 | :style => 'margin-top: 1em' |
1353 | ) | 1353 | ) |
1354 | end | 1354 | end |
1355 | + | ||
1356 | + def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) | ||
1357 | + options[:min_chars] ||= 3 | ||
1358 | + options[:hint_text] ||= _("Type in a search term") | ||
1359 | + options[:no_results_text] ||= _("No results") | ||
1360 | + options[:searching_text] ||= _("Searching...") | ||
1361 | + options[:search_delay] ||= 1000 | ||
1362 | + options[:prevent_duplicates] ||= true | ||
1363 | + options[:backspace_delete_item] ||= false | ||
1364 | + options[:focus] ||= false | ||
1365 | + options[:avoid_enter] ||= true | ||
1366 | + options[:on_result] ||= 'null' | ||
1367 | + options[:on_add] ||= 'null' | ||
1368 | + options[:on_delete] ||= 'null' | ||
1369 | + options[:on_ready] ||= 'null' | ||
1370 | + | ||
1371 | + result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) | ||
1372 | + result += | ||
1373 | + " | ||
1374 | + <script type='text/javascript'> | ||
1375 | + jQuery('##{element_id}') | ||
1376 | + .tokenInput('#{url_for(search_action)}', { | ||
1377 | + minChars: #{options[:min_chars].to_json}, | ||
1378 | + prePopulate: #{options[:pre_populate].to_json}, | ||
1379 | + hintText: #{options[:hint_text].to_json}, | ||
1380 | + noResultsText: #{options[:no_results_text].to_json}, | ||
1381 | + searchingText: #{options[:searching_text].to_json}, | ||
1382 | + searchDelay: #{options[:serach_delay].to_json}, | ||
1383 | + preventDuplicates: #{options[:prevent_duplicates].to_json}, | ||
1384 | + backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, | ||
1385 | + queryParam: #{name.to_json}, | ||
1386 | + tokenLimit: #{options[:token_limit].to_json}, | ||
1387 | + onResult: #{options[:on_result]}, | ||
1388 | + onAdd: #{options[:on_add]}, | ||
1389 | + onDelete: #{options[:on_delete]}, | ||
1390 | + onReady: #{options[:on_ready]}, | ||
1391 | + }) | ||
1392 | + " | ||
1393 | + result += options[:focus] ? ".focus();" : ";" | ||
1394 | + if options[:avoid_enter] | ||
1395 | + result += "jQuery('#token-input-#{element_id}') | ||
1396 | + .live('keydown', function(event){ | ||
1397 | + if(event.keyCode == '13') return false; | ||
1398 | + });" | ||
1399 | + end | ||
1400 | + result += "</script>" | ||
1401 | + result | ||
1402 | + end | ||
1403 | + | ||
1355 | end | 1404 | end |
app/models/person.rb
@@ -22,7 +22,22 @@ class Person < Profile | @@ -22,7 +22,22 @@ class Person < Profile | ||
22 | super | 22 | super |
23 | end | 23 | end |
24 | 24 | ||
25 | - named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } } | 25 | + acts_as_having_hotspots |
26 | + | ||
27 | + named_scope :members_of, lambda { |resources| | ||
28 | + resources = [resources] if !resources.kind_of?(Array) | ||
29 | + conditions = resources.map {|resource| "role_assignments.resource_type = '#{resource.class.base_class.name}' AND role_assignments.resource_id = #{resource.id || -1}"}.join(' OR ') | ||
30 | + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } | ||
31 | + } | ||
32 | + | ||
33 | + def has_permission_with_plugins?(permission, profile) | ||
34 | + permissions = [has_permission_without_plugins?(permission, profile)] | ||
35 | + permissions += enabled_plugins.map do |plugin| | ||
36 | + plugin.has_permission?(self, permission, profile) | ||
37 | + end | ||
38 | + permissions.include?(true) | ||
39 | + end | ||
40 | + alias_method_chain :has_permission?, :plugins | ||
26 | 41 | ||
27 | def memberships | 42 | def memberships |
28 | Profile.memberships_of(self) | 43 | Profile.memberships_of(self) |
app/models/profile.rb
@@ -60,6 +60,7 @@ class Profile < ActiveRecord::Base | @@ -60,6 +60,7 @@ class Profile < ActiveRecord::Base | ||
60 | } | 60 | } |
61 | 61 | ||
62 | acts_as_accessible | 62 | acts_as_accessible |
63 | + acts_as_having_hotspots | ||
63 | 64 | ||
64 | named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } | 65 | named_scope :memberships_of, lambda { |person| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.accessor_type = ? AND role_assignments.accessor_id = ?', person.class.base_class.name, person.id ] } } |
65 | #FIXME: these will work only if the subclass is already loaded | 66 | #FIXME: these will work only if the subclass is already loaded |
@@ -68,13 +69,24 @@ class Profile < ActiveRecord::Base | @@ -68,13 +69,24 @@ class Profile < ActiveRecord::Base | ||
68 | named_scope :templates, :conditions => {:is_template => true} | 69 | named_scope :templates, :conditions => {:is_template => true} |
69 | 70 | ||
70 | def members | 71 | def members |
71 | - Person.members_of(self) | 72 | + scopes = dispatch_scopes(:organization_members, self) |
73 | + scopes << Person.members_of(self) | ||
74 | + scopes.size == 1 ? scopes.first : Person.or_scope(scopes) | ||
72 | end | 75 | end |
73 | 76 | ||
74 | def members_count | 77 | def members_count |
75 | - members.count('DISTINCT(profiles.id)') | 78 | + members.count |
76 | end | 79 | end |
77 | 80 | ||
81 | + class << self | ||
82 | + def count_with_distinct(*args) | ||
83 | + options = args.last || {} | ||
84 | + count_without_distinct(:id, {:distinct => true}.merge(options)) | ||
85 | + end | ||
86 | + alias_method_chain :count, :distinct | ||
87 | + end | ||
88 | + | ||
89 | + | ||
78 | def members_by_role(role) | 90 | def members_by_role(role) |
79 | Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) | 91 | Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) |
80 | end | 92 | end |
app/models/profile_list_block.rb
@@ -25,7 +25,7 @@ class ProfileListBlock < Block | @@ -25,7 +25,7 @@ class ProfileListBlock < Block | ||
25 | end | 25 | end |
26 | 26 | ||
27 | def profile_count | 27 | def profile_count |
28 | - profiles.visible.count('DISTINCT(profiles.id)') | 28 | + profiles.visible.count |
29 | end | 29 | end |
30 | 30 | ||
31 | # the title of the block. Probably will be overriden in subclasses. | 31 | # the title of the block. Probably will be overriden in subclasses. |
app/views/enterprise_registration/basic_information.rhtml
@@ -28,6 +28,12 @@ | @@ -28,6 +28,12 @@ | ||
28 | <%= hidden_field_tag 'create_enterprise[target_id]', environment.id %> | 28 | <%= hidden_field_tag 'create_enterprise[target_id]', environment.id %> |
29 | <% end %> | 29 | <% end %> |
30 | 30 | ||
31 | + <% @plugins.dispatch(:enterprise_registration_hidden_fields).each do |field| %> | ||
32 | + <% field.each do |key, value| %> | ||
33 | + <%= f.hidden_field(key, :value => value) %> | ||
34 | + <% end %> | ||
35 | + <% end %> | ||
36 | + | ||
31 | <%= template_options(Enterprise, 'create_enterprise')%> | 37 | <%= template_options(Enterprise, 'create_enterprise')%> |
32 | 38 | ||
33 | <% button_bar do %> | 39 | <% button_bar do %> |
app/views/memberships/index.rhtml
@@ -8,30 +8,6 @@ | @@ -8,30 +8,6 @@ | ||
8 | <%= button :back, _('Go back'), :controller => 'profile_editor' %> | 8 | <%= button :back, _('Go back'), :controller => 'profile_editor' %> |
9 | <% end %> | 9 | <% end %> |
10 | 10 | ||
11 | -<ul> | ||
12 | -<% for membership in @memberships %> | ||
13 | - <li> | ||
14 | - <div class='common-profile-list-block'> | ||
15 | - <%= profile_image_link(membership, :portrait, 'div') %> | ||
16 | - </div> | ||
17 | - <span class='profile-details'> | ||
18 | - <strong><%= membership.name %></strong><br/> | ||
19 | - <%= _('Role: %s') % rolename_for(profile, membership) %> <br/> | ||
20 | - <%= _('Type: %s') % getterm(membership.class.identification) %> <br/> | ||
21 | - <%= _('Description: %s') % membership.description + '<br/>' if membership.community? %> | ||
22 | - <%= _('Members: %s') % membership.members_count.to_s %> <br/> | ||
23 | - <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/> | ||
24 | - <% button_bar do %> | ||
25 | - <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %> | ||
26 | - <%= button 'menu-logout', _('Leave community'), membership.leave_url(true), :class => 'leave-community' %> | ||
27 | - <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %> | ||
28 | - <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %> | ||
29 | - <% end %> | ||
30 | - <% end %> | ||
31 | - </span> | ||
32 | - <br class="may-clear" /> | ||
33 | - </li> | ||
34 | -<% end %> | ||
35 | -</ul> | 11 | +<%= render :partial => 'shared/list_groups', :locals => {:groups => @memberships} %> |
36 | 12 | ||
37 | </div> | 13 | </div> |
app/views/memberships/new_community.rhtml
@@ -16,6 +16,12 @@ | @@ -16,6 +16,12 @@ | ||
16 | 16 | ||
17 | <%= required f.text_field(:name) %> | 17 | <%= required f.text_field(:name) %> |
18 | 18 | ||
19 | + <% @plugins.dispatch(:new_community_hidden_fields).each do |field| %> | ||
20 | + <% field.each do |key, value| %> | ||
21 | + <%= f.hidden_field(key, :value => value) %> | ||
22 | + <% end %> | ||
23 | + <% end %> | ||
24 | + | ||
19 | <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %> | 25 | <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => 'community', :profile => @community } %> |
20 | 26 | ||
21 | <% f.fields_for :image_builder, @community.image do |i| %> | 27 | <% f.fields_for :image_builder, @community.image do |i| %> |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +<ul id="groups-list"> | ||
2 | +<% for group in groups %> | ||
3 | + <li> | ||
4 | + <div class='common-profile-list-block'> | ||
5 | + <%= profile_image_link(group, :portrait, 'div') %> | ||
6 | + </div> | ||
7 | + <span class='profile-details'> | ||
8 | + <strong><%= group.name %></strong><br/> | ||
9 | + <%= _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by_resource_id(group.id) %> | ||
10 | + <%= _('Type: %s') % getterm(group.class.identification) %> <br/> | ||
11 | + <%= _('Description: %s') % group.description + '<br/>' if group.community? %> | ||
12 | + <%= _('Members: %s') % group.members_count.to_s %> <br/> | ||
13 | + <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/> | ||
14 | + <% button_bar do %> | ||
15 | + <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %> | ||
16 | + <%= button 'menu-logout', _('Leave community'), group.leave_url(true), :class => 'leave-community' %> | ||
17 | + <% if (group.community? && user.has_permission?(:destroy_profile, group)) %> | ||
18 | + <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => group.identifier } %> | ||
19 | + <% end %> | ||
20 | + <% end %> | ||
21 | + </span> | ||
22 | + <br class="may-clear" /> | ||
23 | + </li> | ||
24 | +<% end %> | ||
25 | +</ul> | ||
26 | + |
config/initializers/plugins.rb
1 | require 'noosfero/plugin' | 1 | require 'noosfero/plugin' |
2 | +require 'noosfero/plugin/acts_as_having_hotspots' | ||
2 | require 'noosfero/plugin/manager' | 3 | require 'noosfero/plugin/manager' |
3 | require 'noosfero/plugin/active_record' | 4 | require 'noosfero/plugin/active_record' |
4 | require 'noosfero/plugin/mailer_base' | 5 | require 'noosfero/plugin/mailer_base' |
lib/noosfero/plugin.rb
@@ -293,4 +293,29 @@ class Noosfero::Plugin | @@ -293,4 +293,29 @@ class Noosfero::Plugin | ||
293 | nil | 293 | nil |
294 | end | 294 | end |
295 | 295 | ||
296 | + # -> Extends organization list of members | ||
297 | + # returns = An instance of ActiveRecord::NamedScope::Scope retrieved through | ||
298 | + # Person.members_of method. | ||
299 | + def organization_members(organization) | ||
300 | + nil | ||
301 | + end | ||
302 | + | ||
303 | + # -> Extends person permission access | ||
304 | + # returns = boolean | ||
305 | + def has_permission?(person, permission, target) | ||
306 | + nil | ||
307 | + end | ||
308 | + | ||
309 | + # -> Adds hidden_fields to the new community view | ||
310 | + # returns = {key => value} | ||
311 | + def new_community_hidden_fields | ||
312 | + nil | ||
313 | + end | ||
314 | + | ||
315 | + # -> Adds hidden_fields to the enterprise registration view | ||
316 | + # returns = {key => value} | ||
317 | + def enterprise_registration_hidden_fields | ||
318 | + nil | ||
319 | + end | ||
320 | + | ||
296 | end | 321 | end |
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +module ActsAsHavingHotspots | ||
2 | + module ClassMethods | ||
3 | + # Adding this feature to a class demands that it defines an instance method | ||
4 | + # 'environment' that returns the environment associated with the instance. | ||
5 | + def acts_as_having_hotspots | ||
6 | + send :include, InstanceMethods | ||
7 | + end | ||
8 | + | ||
9 | + module InstanceMethods | ||
10 | + # Dispatches +event+ to each enabled plugin and collect the results. | ||
11 | + # | ||
12 | + # Returns an Array containing the objects returned by the event method in | ||
13 | + # each plugin. This array is compacted (i.e. nils are removed) and flattened | ||
14 | + # (i.e. elements of arrays are added to the resulting array). For example, if | ||
15 | + # the enabled plugins return 1, 0, nil, and [1,2,3], then this method will | ||
16 | + # return [1,0,1,2,3] | ||
17 | + # | ||
18 | + def dispatch(event, *args) | ||
19 | + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact.flatten | ||
20 | + end | ||
21 | + | ||
22 | + # Dispatch without flatten since scopes are executed if you run flatten on them | ||
23 | + def dispatch_scopes(event, *args) | ||
24 | + enabled_plugins.map { |plugin| plugin.send(event, *args) }.compact | ||
25 | + end | ||
26 | + | ||
27 | + def enabled_plugins | ||
28 | + Thread.current[:enabled_plugins] ||= (Noosfero::Plugin.all & environment.enabled_plugins).map do |plugin_name| | ||
29 | + plugin = plugin_name.constantize.new | ||
30 | + plugin.context = context | ||
31 | + plugin | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + if !method_defined?(:context) | ||
36 | + define_method(:context) do | ||
37 | + Noosfero::Plugin::Context.new | ||
38 | + end | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | +end | ||
43 | + | ||
44 | +ActiveRecord::Base.send(:extend, ActsAsHavingHotspots::ClassMethods) |
lib/noosfero/plugin/manager.rb
@@ -8,6 +8,7 @@ class Noosfero::Plugin::Manager | @@ -8,6 +8,7 @@ class Noosfero::Plugin::Manager | ||
8 | @constantize = context | 8 | @constantize = context |
9 | end | 9 | end |
10 | 10 | ||
11 | + delegate :environment, :to => :context | ||
11 | delegate :each, :to => :enabled_plugins | 12 | delegate :each, :to => :enabled_plugins |
12 | include Enumerable | 13 | include Enumerable |
13 | 14 |
plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +class SubOrganizationsPluginMyprofileController < MyProfileController | ||
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../views') | ||
3 | + | ||
4 | + before_filter :organizations_only | ||
5 | + protect 'edit_profile', :profile | ||
6 | + | ||
7 | + def index | ||
8 | + @children = SubOrganizationsPlugin::Relation.children(profile) | ||
9 | + @tokenized_children = prepare_to_token_input(@children) | ||
10 | + @pending_children = SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(profile) | ||
11 | + if request.post? | ||
12 | + begin | ||
13 | + original = SubOrganizationsPlugin::Relation.children(profile) | ||
14 | + requested = Organization.find(params[:q].split(',')) | ||
15 | + added = requested - original | ||
16 | + removed = original - requested | ||
17 | + added.each do |organization| | ||
18 | + if current_person.has_permission?('perform_task',organization) | ||
19 | + SubOrganizationsPlugin::Relation.add_children(profile, organization) | ||
20 | + else | ||
21 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => user, :temp_parent_type => profile.class.name, :temp_parent_id => profile.id, :target => organization) | ||
22 | + end | ||
23 | + end | ||
24 | + SubOrganizationsPlugin::Relation.remove_children(profile,removed) | ||
25 | + session[:notice] = _('Sub-organizations updated') | ||
26 | + rescue Exception => exception | ||
27 | + logger.error(exception.to_s) | ||
28 | + session[:notice] = _('Sub-organizations could not be updated') | ||
29 | + end | ||
30 | + redirect_to :action => :index | ||
31 | + end | ||
32 | + end | ||
33 | + | ||
34 | + def search_organization | ||
35 | + render :text => prepare_to_token_input(environment.organizations.find(:all, :conditions => | ||
36 | + ["(LOWER(name) LIKE ? OR LOWER(identifier) LIKE ?) | ||
37 | + AND (identifier NOT LIKE ?) AND (id != ?)", | ||
38 | + "%#{params[:q]}%", "%#{params[:q]}%", "%_template", profile.id]). | ||
39 | + select { |organization| | ||
40 | + SubOrganizationsPlugin::Relation.children(organization).blank? && | ||
41 | + !SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(profile).include?(organization) | ||
42 | + }).to_json | ||
43 | + end | ||
44 | + | ||
45 | + private | ||
46 | + | ||
47 | + def organizations_only | ||
48 | + render_not_found if !profile.organization? | ||
49 | + end | ||
50 | + | ||
51 | + def prepare_to_token_input(array) | ||
52 | + array.map { |object| {:id => object.id, :name => object.name} } | ||
53 | + end | ||
54 | +end |
plugins/sub_organizations/db/migrate/20120530173629_create_relation.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +class CreateRelation < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :sub_organizations_plugin_relations do |t| | ||
4 | + t.references :parent, :polymorphic => true | ||
5 | + t.references :child, :polymorphic => true | ||
6 | + end | ||
7 | + end | ||
8 | + | ||
9 | + def self.down | ||
10 | + drop_table :sub_organizations_plugin_relations | ||
11 | + end | ||
12 | +end |
plugins/sub_organizations/db/migrate/20120615202224_approve_paternity_relation.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class ApprovePaternityRelation < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :sub_organizations_plugin_approve_paternity_relations do |t| | ||
4 | + t.references :task | ||
5 | + t.references :parent, :polymorphic => true | ||
6 | + t.references :child, :polymorphic => true | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + drop_table :sub_organizations_plugin_approve_paternity_relations | ||
12 | + end | ||
13 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin.rb
0 → 100644
@@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
1 | +require_dependency 'sub_organizations_plugin/ext/organization' | ||
2 | +require_dependency 'sub_organizations_plugin/ext/create_enterprise' | ||
3 | + | ||
4 | +class SubOrganizationsPlugin < Noosfero::Plugin | ||
5 | + | ||
6 | + def self.plugin_name | ||
7 | + _("Sub-groups") | ||
8 | + end | ||
9 | + | ||
10 | + def self.plugin_description | ||
11 | + _("Adds the ability for groups to have sub-groups.") | ||
12 | + end | ||
13 | + | ||
14 | + def control_panel_buttons | ||
15 | + if context.profile.organization? && SubOrganizationsPlugin::Relation.parents(context.profile).blank? | ||
16 | + { :title => _('Manage sub-groups'), :icon => 'groups', :url => {:controller => 'sub_organizations_plugin_myprofile'} } | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
20 | + def stylesheet? | ||
21 | + true | ||
22 | + end | ||
23 | + | ||
24 | + def organization_members(organization) | ||
25 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
26 | + Person.members_of(children) if children.present? | ||
27 | + end | ||
28 | + | ||
29 | + def has_permission?(person, permission, target) | ||
30 | + if !target.kind_of?(Environment) && target.organization? | ||
31 | + SubOrganizationsPlugin::Relation.parents(target).map do |parent| | ||
32 | + person.has_permission_without_plugins?(permission, parent) | ||
33 | + end.include?(true) | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + def new_community_hidden_fields | ||
38 | + parent_to_be = context.params[:sub_organizations_plugin_parent_to_be] | ||
39 | + {'sub_organizations_plugin_parent_to_be' => parent_to_be} if parent_to_be.present? | ||
40 | + end | ||
41 | + | ||
42 | + def enterprise_registration_hidden_fields | ||
43 | + parent_to_be = context.params[:sub_organizations_plugin_parent_to_be] | ||
44 | + {'sub_organizations_plugin_parent_to_be' => parent_to_be} if parent_to_be.present? | ||
45 | + end | ||
46 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/approve_paternity.rb
0 → 100644
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +class SubOrganizationsPlugin::ApprovePaternity < Task | ||
2 | + validates_presence_of :requestor, :target | ||
3 | + | ||
4 | + settings_items :temp_parent_id | ||
5 | + settings_items :temp_parent_type | ||
6 | + | ||
7 | + after_create do |task| | ||
8 | + r = SubOrganizationsPlugin::ApprovePaternityRelation.create!(:task => task, :parent => task.temp_parent, :child => task.target) | ||
9 | + end | ||
10 | + | ||
11 | + def temp_parent | ||
12 | + temp_parent_type.constantize.find(temp_parent_id) | ||
13 | + end | ||
14 | + | ||
15 | + def parent | ||
16 | + SubOrganizationsPlugin::ApprovePaternityRelation.parent(self) | ||
17 | + end | ||
18 | + | ||
19 | + def title | ||
20 | + _("Paternity request") | ||
21 | + end | ||
22 | + | ||
23 | + def linked_subject | ||
24 | + {:text => parent.name, :url => parent.url} | ||
25 | + end | ||
26 | + | ||
27 | + def information | ||
28 | + {:message => _('%{requestor} wants to add this organization as a sub-organization of %{linked_subject}.')} | ||
29 | + end | ||
30 | + | ||
31 | + def reject_details | ||
32 | + true | ||
33 | + end | ||
34 | + | ||
35 | + def icon | ||
36 | + {:type => :profile_image, :profile => parent, :url => parent.url} | ||
37 | + end | ||
38 | + | ||
39 | + def task_created_message | ||
40 | + ('%{requestor} wants to add your organization %{target} as a sub-organization of %{parent}.') % {:requestor => requestor.name, :target => target.name, :parent => temp_parent.name} | ||
41 | + end | ||
42 | + | ||
43 | + def task_finished_message | ||
44 | + ('%{target} accepted your request to add it as a sub-organization of %{parent}.') % {:target => target.name, :parent => parent.name} | ||
45 | + end | ||
46 | + | ||
47 | + def task_cancelled_message | ||
48 | + ('%{target} refused your request to add it as a sub-organization of %{parent}.') % {:target => target.name, :parent => parent.name} | ||
49 | + end | ||
50 | + | ||
51 | + protected | ||
52 | + | ||
53 | + def perform | ||
54 | + SubOrganizationsPlugin::Relation.add_children(parent, target) | ||
55 | + end | ||
56 | + | ||
57 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/approve_paternity_relation.rb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +class SubOrganizationsPlugin::ApprovePaternityRelation < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :task | ||
3 | + belongs_to :parent, :polymorphic => true | ||
4 | + belongs_to :child, :polymorphic => true | ||
5 | + | ||
6 | + validates_presence_of :task, :parent, :child | ||
7 | + | ||
8 | + class << self | ||
9 | + def parent(task) | ||
10 | + find_by_task_id(task.id).parent | ||
11 | + end | ||
12 | + | ||
13 | + def pending_children(parent) | ||
14 | + options = { | ||
15 | + :select => "distinct profiles.*", | ||
16 | + :joins => "inner join sub_organizations_plugin_approve_paternity_relations as relations on profiles.id=relations.child_id inner join tasks on relations.task_id=tasks.id", | ||
17 | + :conditions => ["relations.parent_id = ? AND tasks.status = 1", parent.id] | ||
18 | + } | ||
19 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
20 | + end | ||
21 | + end | ||
22 | + | ||
23 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/ext/create_enterprise.rb
0 → 100644
plugins/sub_organizations/lib/sub_organizations_plugin/ext/organization.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +require_dependency 'organization' | ||
2 | +class Organization | ||
3 | + settings_items :sub_organizations_plugin_parent_to_be | ||
4 | + | ||
5 | + after_create do |organization| | ||
6 | + if organization.sub_organizations_plugin_parent_to_be.present? | ||
7 | + parent = Organization.find(organization.sub_organizations_plugin_parent_to_be) | ||
8 | + SubOrganizationsPlugin::Relation.add_children(parent,organization) | ||
9 | + end | ||
10 | + end | ||
11 | + | ||
12 | + FIELDS << 'sub_organizations_plugin_parent_to_be' | ||
13 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/relation.rb
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +class SubOrganizationsPlugin::Relation < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :parent, :polymorphic => true | ||
3 | + belongs_to :child, :polymorphic => true | ||
4 | + | ||
5 | + validates_presence_of :parent, :child | ||
6 | + validate :no_self_reference | ||
7 | + validate :no_cyclical_reference, :if => 'parent.present? && child.present?' | ||
8 | + validate :no_multi_level, :if => 'parent.present? && child.present?' | ||
9 | + | ||
10 | + def no_self_reference | ||
11 | + errors.add(:child, _('self-reference is not allowed.')) if parent == child | ||
12 | + end | ||
13 | + | ||
14 | + def no_cyclical_reference | ||
15 | + if self.class.children(child).include?(parent) | ||
16 | + errors.add(:child, _('cyclical reference is not allowed.')) | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
20 | + def no_multi_level | ||
21 | + if self.class.parents(parent).present? || self.class.children(child).present? | ||
22 | + errors.add(:child, _('multi-level paternity is not allowed.')) | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + class << self | ||
27 | + def children(parent) | ||
28 | + options = { | ||
29 | + :select => "profiles.*", | ||
30 | + :joins => "inner join sub_organizations_plugin_relations as relations on profiles.id=relations.child_id", | ||
31 | + :conditions => ["relations.parent_id = ?", parent.id] | ||
32 | + } | ||
33 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
34 | + end | ||
35 | + | ||
36 | + def parents(child) | ||
37 | + options = { | ||
38 | + :select => "profiles.*", | ||
39 | + :joins => "inner join sub_organizations_plugin_relations as relations on profiles.id=relations.parent_id", | ||
40 | + :conditions => ["relations.child_id = ?", child.id] | ||
41 | + } | ||
42 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
43 | + end | ||
44 | + | ||
45 | + def add_children(parent, *children) | ||
46 | + children.each {|child| create!(:parent => parent, :child => child)} | ||
47 | + end | ||
48 | + | ||
49 | + def remove_children(parent, *children) | ||
50 | + children.flatten.each {|child| find_by_parent_id_and_child_id(parent.id, child.id).destroy} | ||
51 | + end | ||
52 | + end | ||
53 | + | ||
54 | +end |
plugins/sub_organizations/test/functional/sub_organizations_plugin_myprofile_controller_test.rb
0 → 100644
@@ -0,0 +1,113 @@ | @@ -0,0 +1,113 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/sub_organizations_plugin_myprofile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class SubOrganizationsPluginMyprofileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class SubOrganizationsPluginMyprofileControllerTest < ActionController::TestCase | ||
8 | + def setup | ||
9 | + @controller = SubOrganizationsPluginMyprofileController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + @organization = Organization.create!(:name => 'My Organization', :identifier => 'my-organization') | ||
13 | + @person = create_user('person').person | ||
14 | + @organization.add_admin(@person) | ||
15 | + login_as(@person.user.login) | ||
16 | + e = Environment.default | ||
17 | + e.enable_plugin('SubOrganizationsPlugin') | ||
18 | + e.save! | ||
19 | + end | ||
20 | + | ||
21 | + attr_accessor :person, :organization | ||
22 | + | ||
23 | + should 'search organizations' do | ||
24 | + # Should list if match name | ||
25 | + o1 = fast_create(Organization, :name => 'sample organization 1') | ||
26 | + # Should be case insensitive | ||
27 | + o2 = fast_create(Organization, :name => 'SaMpLe OrGaNiZaTiOn 2') | ||
28 | + # Should not list if don't match name | ||
29 | + o3 = fast_create(Organization, :name => 'blo') | ||
30 | + # Should not list if is has children | ||
31 | + child = fast_create(Organization) | ||
32 | + o4 = fast_create(Organization, :name => 'sample organization 4') | ||
33 | + SubOrganizationsPlugin::Relation.add_children(o4, child) | ||
34 | + # Should not list if is there is a task to add it | ||
35 | + o5 = fast_create(Organization, :name => 'sample enterprise 5') | ||
36 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => person, :target => o5, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
37 | + # Should search by identifier | ||
38 | + o6 = fast_create(Organization, :name => 'Bla', :identifier => 'sample-enterprise-6') | ||
39 | + # Should not list itself | ||
40 | + organization.name = 'Sample Organization' | ||
41 | + organization.save! | ||
42 | + | ||
43 | + get :search_organization, :profile => organization.identifier, :q => 'sampl' | ||
44 | + | ||
45 | + assert_match /#{o1.name}/, @response.body | ||
46 | + assert_match /#{o2.name}/, @response.body | ||
47 | + assert_no_match /#{o3.name}/, @response.body | ||
48 | + assert_no_match /#{o4.name}/, @response.body | ||
49 | + assert_no_match /#{o5.name}/, @response.body | ||
50 | + assert_match /#{o6.name}/, @response.body | ||
51 | + assert_no_match /#{organization.name}/, @response.body | ||
52 | + end | ||
53 | + | ||
54 | + should 'update sub-organizations list' do | ||
55 | + org1 = fast_create(Organization) | ||
56 | + org2 = fast_create(Organization) | ||
57 | + org3 = fast_create(Organization) | ||
58 | + org4 = fast_create(Organization) | ||
59 | + SubOrganizationsPlugin::Relation.add_children(organization, org1, org2) | ||
60 | + | ||
61 | + post :index, :profile => organization.identifier, :q => [org2,org3,org4].map(&:id).join(',') | ||
62 | + | ||
63 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
64 | + assert_not_includes children, org1 | ||
65 | + assert_includes children, org2 | ||
66 | + assert_not_includes children, org3 | ||
67 | + assert_not_includes children, org4 | ||
68 | + | ||
69 | + SubOrganizationsPlugin::ApprovePaternity.all.map(&:finish) | ||
70 | + | ||
71 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
72 | + assert_not_includes children, org1 | ||
73 | + assert_includes children, org2 | ||
74 | + assert_includes children, org3 | ||
75 | + assert_includes children, org4 | ||
76 | + end | ||
77 | + | ||
78 | + should 'establish relation right away if the user can perform tasks on the sub-organization' do | ||
79 | + org1 = fast_create(Organization) | ||
80 | + org2 = fast_create(Organization) | ||
81 | + org2.add_admin(person) | ||
82 | + | ||
83 | + assert_difference SubOrganizationsPlugin::ApprovePaternity, :count, 1 do | ||
84 | + post :index, :profile => organization.identifier, :q => [org1,org2].map(&:id).join(',') | ||
85 | + end | ||
86 | + assert_includes SubOrganizationsPlugin::Relation.children(organization), org2 | ||
87 | + end | ||
88 | + | ||
89 | + should 'not access index if dont have permission' do | ||
90 | + member = create_user('member').person | ||
91 | + organization.add_member(member) | ||
92 | + | ||
93 | + login_as(member.identifier) | ||
94 | + get :index, :profile => organization.identifier | ||
95 | + | ||
96 | + assert_response 403 | ||
97 | + assert_template 'access_denied.rhtml' | ||
98 | + end | ||
99 | + | ||
100 | + should 'not search organizations if dont have permission' do | ||
101 | + member = create_user('member').person | ||
102 | + organization.add_member(member) | ||
103 | + | ||
104 | + login_as(member.identifier) | ||
105 | + | ||
106 | + org1 = fast_create(Organization, :name => 'sample organization 1') | ||
107 | + get :search_organization, :profile => organization.identifier, :q => 'sampl' | ||
108 | + | ||
109 | + assert_response 403 | ||
110 | + assert_template 'access_denied.rhtml' | ||
111 | + end | ||
112 | + | ||
113 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/approve_paternity_relation_test.rb
0 → 100644
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::ApprovePaternityRelationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @requestor = create_user('some-user').person | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :requestor | ||
10 | + | ||
11 | + should 'return parent' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + task = SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org2, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name) | ||
15 | + | ||
16 | + assert_equal SubOrganizationsPlugin::ApprovePaternityRelation.parent(task), org1 | ||
17 | + end | ||
18 | + | ||
19 | + should 'list pending children' do | ||
20 | + organization = fast_create(Organization) | ||
21 | + org1 = fast_create(Organization) | ||
22 | + org2 = fast_create(Organization) | ||
23 | + org3 = fast_create(Organization) | ||
24 | + | ||
25 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org1, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
26 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org2, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
27 | + | ||
28 | + assert_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org1 | ||
29 | + assert_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org2 | ||
30 | + assert_not_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org3 | ||
31 | + end | ||
32 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/approve_paternity_test.rb
0 → 100644
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::ApprovePaternityTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @requestor = create_user('some-user').person | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :requestor | ||
10 | + | ||
11 | + should 'create relation after creation' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + assert_difference SubOrganizationsPlugin::ApprovePaternityRelation, :count, 1 do | ||
15 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name, :target => org2) | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
19 | + should 'add children to parent after approving' do | ||
20 | + org1 = fast_create(Organization) | ||
21 | + org2 = fast_create(Organization) | ||
22 | + | ||
23 | + task = SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name, :target => org2) | ||
24 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
25 | + | ||
26 | + task.finish | ||
27 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
28 | + end | ||
29 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/ext/create_enterprise_test.rb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CreateEnterpriseTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'inlude the parent field in create enterprise' do | ||
6 | + create_enterprise = CreateEnterprise.new | ||
7 | + assert_nothing_raised { create_enterprise.sub_organizations_plugin_parent_to_be = '999' } | ||
8 | + end | ||
9 | + | ||
10 | +end | ||
11 | + |
plugins/sub_organizations/test/unit/sub_organizations_plugin/ext/organization.rb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../../test/test_helper' | ||
2 | + | ||
3 | +class OrganizationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'inlude the parent field in organization' do | ||
6 | + organization = Organization.new | ||
7 | + assert_nothing_raised { organization.sub_organizations_plugin_parent_to_be = '999' } | ||
8 | + end | ||
9 | + | ||
10 | + should 'include the parent field in the FIELDS constant' do | ||
11 | + assert_includes Organization::FIELDS, 'sub_organizations_plugin_parent_to_be' | ||
12 | + end | ||
13 | + | ||
14 | + should 'relate organization with parent if the attribute is set' do | ||
15 | + parent = fast_create(Organization) | ||
16 | + organization = Organization.new(:identifier => 'some-org',:name => 'Some Org', :sub_organizations_plugin_parent_to_be => parent.id) | ||
17 | + assert_not_includes SubOrganizationsPlugin::Relation.children(parent), organization | ||
18 | + | ||
19 | + organization.save! | ||
20 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), organization | ||
21 | + end | ||
22 | + | ||
23 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/relation_test.rb
0 → 100644
@@ -0,0 +1,110 @@ | @@ -0,0 +1,110 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::RelationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'validates presence of child and parent' do | ||
6 | + org = fast_create(Organization) | ||
7 | + relation = SubOrganizationsPlugin::Relation.new | ||
8 | + | ||
9 | + relation.parent = org | ||
10 | + relation.valid? | ||
11 | + assert relation.errors.invalid?(:child) | ||
12 | + | ||
13 | + relation.parent = nil | ||
14 | + relation.child = org | ||
15 | + relation.valid? | ||
16 | + assert relation.errors.invalid?(:parent) | ||
17 | + end | ||
18 | + | ||
19 | + should 'relate two organizations' do | ||
20 | + org1 = fast_create(Organization) | ||
21 | + org2 = fast_create(Organization) | ||
22 | + relation = SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
23 | + | ||
24 | + assert_equal org1, relation.parent | ||
25 | + assert_equal org2, relation.child | ||
26 | + end | ||
27 | + | ||
28 | + should 'not allow self relation' do | ||
29 | + org = fast_create(Organization) | ||
30 | + relation = SubOrganizationsPlugin::Relation.new(:parent_id => org, :child_id => org) | ||
31 | + assert !relation.valid? | ||
32 | + assert relation.errors.invalid?(:child) | ||
33 | + end | ||
34 | + | ||
35 | + should 'be able to retrieve parents of an organization' do | ||
36 | + child = fast_create(Organization) | ||
37 | + parent1 = fast_create(Organization) | ||
38 | + parent2 = fast_create(Organization) | ||
39 | + SubOrganizationsPlugin::Relation.create!(:parent => parent1, :child => child) | ||
40 | + SubOrganizationsPlugin::Relation.create!(:parent => parent2, :child => child) | ||
41 | + | ||
42 | + assert_includes SubOrganizationsPlugin::Relation.parents(child), parent1 | ||
43 | + assert_includes SubOrganizationsPlugin::Relation.parents(child), parent2 | ||
44 | + end | ||
45 | + | ||
46 | + should 'be able to retrieve children of an organization' do | ||
47 | + parent = fast_create(Organization) | ||
48 | + child1 = fast_create(Organization) | ||
49 | + child2 = fast_create(Organization) | ||
50 | + SubOrganizationsPlugin::Relation.create!(:parent => parent, :child => child1) | ||
51 | + SubOrganizationsPlugin::Relation.create!(:parent => parent, :child => child2) | ||
52 | + | ||
53 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), child1 | ||
54 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), child2 | ||
55 | + end | ||
56 | + | ||
57 | + should 'not allow cyclical reference' do | ||
58 | + org1 = fast_create(Organization) | ||
59 | + org2 = fast_create(Organization) | ||
60 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
61 | + relation = SubOrganizationsPlugin::Relation.new(:parent => org2, :child => org1) | ||
62 | + | ||
63 | + assert !relation.valid? | ||
64 | + assert relation.errors.invalid?(:child) | ||
65 | + end | ||
66 | + | ||
67 | + should 'not allow multi-level paternity' do | ||
68 | + org1 = fast_create(Organization) | ||
69 | + org2 = fast_create(Organization) | ||
70 | + org3 = fast_create(Organization) | ||
71 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
72 | + r1 = SubOrganizationsPlugin::Relation.new(:parent => org2, :child => org3) | ||
73 | + r2 = SubOrganizationsPlugin::Relation.new(:parent => org3, :child => org1) | ||
74 | + | ||
75 | + assert !r1.valid? | ||
76 | + assert r1.errors.invalid?(:child) | ||
77 | + | ||
78 | + assert !r2.valid? | ||
79 | + assert r2.errors.invalid?(:child) | ||
80 | + end | ||
81 | + | ||
82 | + should 'add children' do | ||
83 | + org1 = fast_create(Organization) | ||
84 | + org2 = fast_create(Organization) | ||
85 | + org3 = fast_create(Organization) | ||
86 | + org4 = fast_create(Organization) | ||
87 | + | ||
88 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
89 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
90 | + | ||
91 | + SubOrganizationsPlugin::Relation.add_children(org1,org3,org4) | ||
92 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org3 | ||
93 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org4 | ||
94 | + end | ||
95 | + | ||
96 | + should 'remove children' do | ||
97 | + org1 = fast_create(Organization) | ||
98 | + org2 = fast_create(Organization) | ||
99 | + org3 = fast_create(Organization) | ||
100 | + org4 = fast_create(Organization) | ||
101 | + SubOrganizationsPlugin::Relation.add_children(org1,org2,org3,org4) | ||
102 | + | ||
103 | + SubOrganizationsPlugin::Relation.remove_children(org1,org2) | ||
104 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
105 | + | ||
106 | + SubOrganizationsPlugin::Relation.remove_children(org1,org3,org4) | ||
107 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org3 | ||
108 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org4 | ||
109 | + end | ||
110 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin_test.rb
0 → 100644
@@ -0,0 +1,83 @@ | @@ -0,0 +1,83 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @plugin = SubOrganizationsPlugin.new | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :plugin | ||
10 | + | ||
11 | + should 'include sub-organizations members in the parent organization' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + org3 = fast_create(Organization) | ||
15 | + member1 = fast_create(Person) | ||
16 | + member2 = fast_create(Person) | ||
17 | + member3 = fast_create(Person) | ||
18 | + member4 = fast_create(Person) | ||
19 | + member5 = fast_create(Person) | ||
20 | + member6 = fast_create(Person) | ||
21 | + member7 = fast_create(Person) | ||
22 | + org1.add_member(member1) | ||
23 | + org2.add_member(member2) | ||
24 | + org2.add_member(member3) | ||
25 | + org3.add_member(member4) | ||
26 | + org3.add_member(member5) | ||
27 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
28 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org3) | ||
29 | + | ||
30 | + org1_members = plugin.organization_members(org1) | ||
31 | + | ||
32 | + assert_equal ActiveRecord::NamedScope::Scope, org1_members.class | ||
33 | + assert_not_includes org1_members, member1 | ||
34 | + assert_includes org1_members, member2 | ||
35 | + assert_includes org1_members, member3 | ||
36 | + assert_includes org1_members, member4 | ||
37 | + assert_includes org1_members, member5 | ||
38 | + assert_not_includes org1_members, member6 | ||
39 | + assert_not_includes org1_members, member7 | ||
40 | + | ||
41 | + org2_members = plugin.organization_members(org2) | ||
42 | + org3_members = plugin.organization_members(org3) | ||
43 | + | ||
44 | + assert org2_members.blank? | ||
45 | + assert org3_members.blank? | ||
46 | + end | ||
47 | + | ||
48 | + should 'grant permission that user has on parent organizations over children orgnaizations' do | ||
49 | + person = create_user('admin-user').person | ||
50 | + org1 = fast_create(Organization) | ||
51 | + org2 = fast_create(Organization) | ||
52 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
53 | + person.stubs('has_permission_without_plugins?').with(:make_ice_cream, org1).returns(true) | ||
54 | + person.stubs('has_permission_without_plugins?').with(:make_ice_cream, org2).returns(false) | ||
55 | + | ||
56 | + assert plugin.has_permission?(person, :make_ice_cream, org2) | ||
57 | + end | ||
58 | + | ||
59 | + should 'not crash if receives an environment as target of has permission' do | ||
60 | + assert_nothing_raised do | ||
61 | + plugin.has_permission?(fast_create(Person), :make_ice_cream, fast_create(Environment)) | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + should 'display control panel button only to organizations with no parent' do | ||
66 | + org1 = fast_create(Organization) | ||
67 | + org2 = fast_create(Organization) | ||
68 | + profile = fast_create(Profile) | ||
69 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
70 | + context = mock() | ||
71 | + SubOrganizationsPlugin.any_instance.stubs(:context).returns(context) | ||
72 | + | ||
73 | + context.stubs(:profile).returns(org1) | ||
74 | + assert_not_nil plugin.control_panel_buttons | ||
75 | + | ||
76 | + context.stubs(:profile).returns(org2) | ||
77 | + assert_nil plugin.control_panel_buttons | ||
78 | + | ||
79 | + context.stubs(:profile).returns(profile) | ||
80 | + assert_nil plugin.control_panel_buttons | ||
81 | + end | ||
82 | +end | ||
83 | + |
plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb
0 → 100644
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +<h1><%= _('Manage sub-groups') %></h1> | ||
2 | + | ||
3 | +<% if !@pending_children.blank? %> | ||
4 | + <%= _('Sub-groups awaiting approval:') %> | ||
5 | + <ul> | ||
6 | + <% @pending_children.each do |child| %> | ||
7 | + <li><%= link_to(child.name, child.url) %></li> | ||
8 | + <% end %> | ||
9 | + </ul> | ||
10 | +<% end %> | ||
11 | + | ||
12 | +<% form_tag do %> | ||
13 | + <% button_bar do %> | ||
14 | + <%= button(:add, __('Create a new sub-community'), :controller => 'memberships', :action => 'new_community', :profile => user.identifier, :sub_organizations_plugin_parent_to_be => profile.id) %> | ||
15 | + <%= button :add, __('Register a new sub-enterprise'), :controller => 'enterprise_registration', :sub_organizations_plugin_parent_to_be => profile.id if environment.enabled?('enterprise_registration') %> | ||
16 | + <% end %> | ||
17 | + | ||
18 | + <p><%= _('Fill in the search field to find the groups that should be added as sub-group of this organization:') %></p> | ||
19 | + <%= token_input_field_tag(:q, 'search-organization', {:action => 'search_organization'}, | ||
20 | + { :focus => true, | ||
21 | + :hint_text => _('Type in a search term for a group'), | ||
22 | + :pre_populate => @tokenized_children}) %> | ||
23 | + | ||
24 | + <% button_bar do %> | ||
25 | + <%= submit_button('save', _('Save'))%> | ||
26 | + <%= button('cancel', _('Cancel'), {:controller => 'profile_editor'})%> | ||
27 | + <% end %> | ||
28 | +<% end %> | ||
29 | + | ||
30 | +<br style='clear: both'/> | ||
31 | + | ||
32 | +<%= render :partial => 'shared/list_groups', :locals => {:profile => user, :groups => @children} %> |
public/stylesheets/application.css
@@ -3598,46 +3598,50 @@ h1#agenda-title { | @@ -3598,46 +3598,50 @@ h1#agenda-title { | ||
3598 | /* ==> public/stylesheets/controller_memberships.css <== */ | 3598 | /* ==> public/stylesheets/controller_memberships.css <== */ |
3599 | /* @import url(profile-list-block.css); ==> BROKEN REFERENCE, OH MY! */ | 3599 | /* @import url(profile-list-block.css); ==> BROKEN REFERENCE, OH MY! */ |
3600 | 3600 | ||
3601 | -.controller-memberships #memberships-index ul { | 3601 | +#groups-list { |
3602 | width: 100%; | 3602 | width: 100%; |
3603 | padding: 0px; | 3603 | padding: 0px; |
3604 | margin: 0px; | 3604 | margin: 0px; |
3605 | display: block; | 3605 | display: block; |
3606 | } | 3606 | } |
3607 | -.controller-memberships #memberships-index li { | 3607 | + |
3608 | +#groups-list li { | ||
3608 | display: block; | 3609 | display: block; |
3609 | list-style: none; | 3610 | list-style: none; |
3610 | margin-bottom: 20px background-color: #B8CFE7; | 3611 | margin-bottom: 20px background-color: #B8CFE7; |
3611 | } | 3612 | } |
3612 | -.controller-memberships #memberships-index li .vcard { | 3613 | + |
3614 | +#groups-list li .vcard { | ||
3613 | float: right; | 3615 | float: right; |
3614 | padding: 5px; | 3616 | padding: 5px; |
3615 | margin-bottom: 5px; | 3617 | margin-bottom: 5px; |
3616 | margin-left: 10px; | 3618 | margin-left: 10px; |
3617 | } | 3619 | } |
3618 | -.controller-memberships #memberships-index li .may-clear { | 3620 | +#groups-list li .may-clear { |
3619 | clear: right; | 3621 | clear: right; |
3620 | } | 3622 | } |
3621 | -.controller-memberships #memberships-index li .profile-details { | 3623 | + |
3624 | +#groups-list li .profile-details { | ||
3622 | display: block; | 3625 | display: block; |
3623 | padding: 3% 0px 0px 30px; | 3626 | padding: 3% 0px 0px 30px; |
3624 | } | 3627 | } |
3625 | -.controller-memberships .action_memberships_destroy_community .main-block u { | ||
3626 | - text-decoration: none; | ||
3627 | - border-bottom: 1px dotted red; | ||
3628 | -} | ||
3629 | -#memberships-index .menu-submenu { | 3628 | + |
3629 | +#groups-list .menu-submenu { | ||
3630 | bottom: 127px; | 3630 | bottom: 127px; |
3631 | right: -20px; | 3631 | right: -20px; |
3632 | } | 3632 | } |
3633 | -#memberships-index .menu-submenu li { | 3633 | + |
3634 | +#groups-list .menu-submenu li { | ||
3634 | border: 0; | 3635 | border: 0; |
3635 | background: transparent; | 3636 | background: transparent; |
3636 | } | 3637 | } |
3637 | -.controller-memberships .button-bar { | 3638 | + |
3639 | +#groups-list .button-bar { | ||
3638 | clear: both; | 3640 | clear: both; |
3639 | } | 3641 | } |
3640 | -.controller-memberships #memberships-index li .vcard a.profile_link.url, .controller-memberships #memberships-index li .vcard a.profile_link.url:hover { | 3642 | + |
3643 | +#groups-list li .vcard a.profile_link.url, | ||
3644 | +#groups-list li .vcard a.profile_link.url:hover { | ||
3641 | background: transparent; | 3645 | background: transparent; |
3642 | border: 0; | 3646 | border: 0; |
3643 | text-decoration: none; | 3647 | text-decoration: none; |
test/functional/enterprise_registration_controller_test.rb
@@ -180,4 +180,27 @@ class EnterpriseRegistrationControllerTest < ActionController::TestCase | @@ -180,4 +180,27 @@ class EnterpriseRegistrationControllerTest < ActionController::TestCase | ||
180 | get :index | 180 | get :index |
181 | assert_equal assigns(:create_enterprise).target, environment | 181 | assert_equal assigns(:create_enterprise).target, environment |
182 | end | 182 | end |
183 | + | ||
184 | + should 'include hidden fields supplied by plugins on enterprise registration' do | ||
185 | + class Plugin1 < Noosfero::Plugin | ||
186 | + def enterprise_registration_hidden_fields | ||
187 | + {'plugin1' => 'Plugin 1'} | ||
188 | + end | ||
189 | + end | ||
190 | + | ||
191 | + class Plugin2 < Noosfero::Plugin | ||
192 | + def enterprise_registration_hidden_fields | ||
193 | + {'plugin2' => 'Plugin 2'} | ||
194 | + end | ||
195 | + end | ||
196 | + | ||
197 | + environment = Environment.default | ||
198 | + environment.enable_plugin(Plugin1.name) | ||
199 | + environment.enable_plugin(Plugin2.name) | ||
200 | + | ||
201 | + get :index | ||
202 | + | ||
203 | + assert_tag :tag => 'input', :attributes => {:id => 'create_enterprise_plugin1', :type => 'hidden', :value => 'Plugin 1'} | ||
204 | + assert_tag :tag => 'input', :attributes => {:id => 'create_enterprise_plugin2', :type => 'hidden', :value => 'Plugin 2'} | ||
205 | + end | ||
183 | end | 206 | end |
test/functional/memberships_controller_test.rb
@@ -206,4 +206,27 @@ class MembershipsControllerTest < ActionController::TestCase | @@ -206,4 +206,27 @@ class MembershipsControllerTest < ActionController::TestCase | ||
206 | assert_no_tag :tag => 'textarea', :attributes => {:name => 'community[description]'} | 206 | assert_no_tag :tag => 'textarea', :attributes => {:name => 'community[description]'} |
207 | end | 207 | end |
208 | 208 | ||
209 | + should 'include hidden fields supplied by plugins on new community' do | ||
210 | + class Plugin1 < Noosfero::Plugin | ||
211 | + def new_community_hidden_fields | ||
212 | + {'plugin1' => 'Plugin 1'} | ||
213 | + end | ||
214 | + end | ||
215 | + | ||
216 | + class Plugin2 < Noosfero::Plugin | ||
217 | + def new_community_hidden_fields | ||
218 | + {'plugin2' => 'Plugin 2'} | ||
219 | + end | ||
220 | + end | ||
221 | + | ||
222 | + environment = Environment.default | ||
223 | + environment.enable_plugin(Plugin1.name) | ||
224 | + environment.enable_plugin(Plugin2.name) | ||
225 | + | ||
226 | + get :new_community, :profile => profile.identifier | ||
227 | + | ||
228 | + assert_tag :tag => 'input', :attributes => {:id => 'community_plugin1', :type => 'hidden', :value => 'Plugin 1'} | ||
229 | + assert_tag :tag => 'input', :attributes => {:id => 'community_plugin2', :type => 'hidden', :value => 'Plugin 2'} | ||
230 | + end | ||
231 | + | ||
209 | end | 232 | end |
test/unit/person_test.rb
@@ -3,6 +3,10 @@ require File.dirname(__FILE__) + '/../test_helper' | @@ -3,6 +3,10 @@ require File.dirname(__FILE__) + '/../test_helper' | ||
3 | class PersonTest < ActiveSupport::TestCase | 3 | class PersonTest < ActiveSupport::TestCase |
4 | fixtures :profiles, :users, :environments | 4 | fixtures :profiles, :users, :environments |
5 | 5 | ||
6 | + def teardown | ||
7 | + Thread.current[:enabled_plugins] = nil | ||
8 | + end | ||
9 | + | ||
6 | def test_person_must_come_form_the_cration_of_an_user | 10 | def test_person_must_come_form_the_cration_of_an_user |
7 | p = Person.new(:environment => Environment.default, :name => 'John', :identifier => 'john') | 11 | p = Person.new(:environment => Environment.default, :name => 'John', :identifier => 'john') |
8 | assert !p.valid? | 12 | assert !p.valid? |
@@ -1104,6 +1108,18 @@ class PersonTest < ActiveSupport::TestCase | @@ -1104,6 +1108,18 @@ class PersonTest < ActiveSupport::TestCase | ||
1104 | assert_equal [person], Person.members_of(community) | 1108 | assert_equal [person], Person.members_of(community) |
1105 | end | 1109 | end |
1106 | 1110 | ||
1111 | + should 'be able to pass array to members_of' do | ||
1112 | + person1 = fast_create(Person) | ||
1113 | + community = fast_create(Community) | ||
1114 | + community.add_member(person1) | ||
1115 | + person2 = fast_create(Person) | ||
1116 | + enterprise = fast_create(Enterprise) | ||
1117 | + enterprise.add_member(person2) | ||
1118 | + | ||
1119 | + assert_includes Person.members_of([community, enterprise]), person1 | ||
1120 | + assert_includes Person.members_of([community, enterprise]), person2 | ||
1121 | + end | ||
1122 | + | ||
1107 | should 'find more active people' do | 1123 | should 'find more active people' do |
1108 | Person.destroy_all | 1124 | Person.destroy_all |
1109 | p1 = fast_create(Person) | 1125 | p1 = fast_create(Person) |
@@ -1228,4 +1244,26 @@ class PersonTest < ActiveSupport::TestCase | @@ -1228,4 +1244,26 @@ class PersonTest < ActiveSupport::TestCase | ||
1228 | 1244 | ||
1229 | assert_equivalent [person_scrap,person_activity], person.activities.map { |a| a.klass.constantize.find(a.id) } | 1245 | assert_equivalent [person_scrap,person_activity], person.activities.map { |a| a.klass.constantize.find(a.id) } |
1230 | end | 1246 | end |
1247 | + | ||
1248 | + should 'allow plugins to extend person\'s permission access' do | ||
1249 | + person = create_user('some-user').person | ||
1250 | + class Plugin1 < Noosfero::Plugin | ||
1251 | + def has_permission?(person, permission, target) | ||
1252 | + true | ||
1253 | + end | ||
1254 | + end | ||
1255 | + | ||
1256 | + class Plugin2 < Noosfero::Plugin | ||
1257 | + def has_permission?(person, permission, target) | ||
1258 | + false | ||
1259 | + end | ||
1260 | + end | ||
1261 | + | ||
1262 | + e = Environment.default | ||
1263 | + e.enable_plugin(Plugin1.name) | ||
1264 | + e.enable_plugin(Plugin2.name) | ||
1265 | + person.stubs('has_permission_without_plugins?').returns(false) | ||
1266 | + | ||
1267 | + assert person.has_permission?('bli', Profile.new) | ||
1268 | + end | ||
1231 | end | 1269 | end |
test/unit/plugin_manager_test.rb
@@ -12,7 +12,6 @@ class PluginManagerTest < ActiveSupport::TestCase | @@ -12,7 +12,6 @@ class PluginManagerTest < ActiveSupport::TestCase | ||
12 | @manager = Noosfero::Plugin::Manager.new(@environment, @controller) | 12 | @manager = Noosfero::Plugin::Manager.new(@environment, @controller) |
13 | end | 13 | end |
14 | attr_reader :environment | 14 | attr_reader :environment |
15 | - attr_reader :manager | ||
16 | 15 | ||
17 | should 'return the intersection between environment\'s enabled plugins and system available plugins' do | 16 | should 'return the intersection between environment\'s enabled plugins and system available plugins' do |
18 | class Plugin1 < Noosfero::Plugin; end; | 17 | class Plugin1 < Noosfero::Plugin; end; |
@@ -21,6 +20,7 @@ class PluginManagerTest < ActiveSupport::TestCase | @@ -21,6 +20,7 @@ class PluginManagerTest < ActiveSupport::TestCase | ||
21 | class Plugin4 < Noosfero::Plugin; end; | 20 | class Plugin4 < Noosfero::Plugin; end; |
22 | environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s]) | 21 | environment.stubs(:enabled_plugins).returns([Plugin1.to_s, Plugin2.to_s, Plugin4.to_s]) |
23 | Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s]) | 22 | Noosfero::Plugin.stubs(:all).returns([Plugin1.to_s, Plugin3.to_s, Plugin4.to_s]) |
23 | + manager = Noosfero::Plugin::Manager.new(@controller) | ||
24 | plugins = manager.enabled_plugins.map { |instance| instance.class.to_s } | 24 | plugins = manager.enabled_plugins.map { |instance| instance.class.to_s } |
25 | assert_equal [Plugin1.to_s, Plugin4.to_s], plugins | 25 | assert_equal [Plugin1.to_s, Plugin4.to_s], plugins |
26 | end | 26 | end |
@@ -49,6 +49,7 @@ class PluginManagerTest < ActiveSupport::TestCase | @@ -49,6 +49,7 @@ class PluginManagerTest < ActiveSupport::TestCase | ||
49 | 49 | ||
50 | p1 = Plugin1.new | 50 | p1 = Plugin1.new |
51 | p2 = Plugin2.new | 51 | p2 = Plugin2.new |
52 | + manager = Noosfero::Plugin::Manager.new(@controller) | ||
52 | 53 | ||
53 | assert_equal [p1.random_event, p2.random_event], manager.dispatch(:random_event) | 54 | assert_equal [p1.random_event, p2.random_event], manager.dispatch(:random_event) |
54 | end | 55 | end |
test/unit/profile_test.rb
@@ -3,8 +3,8 @@ require File.dirname(__FILE__) + '/../test_helper' | @@ -3,8 +3,8 @@ require File.dirname(__FILE__) + '/../test_helper' | ||
3 | class ProfileTest < ActiveSupport::TestCase | 3 | class ProfileTest < ActiveSupport::TestCase |
4 | fixtures :profiles, :environments, :users, :roles, :domains | 4 | fixtures :profiles, :environments, :users, :roles, :domains |
5 | 5 | ||
6 | - def setup | ||
7 | - super | 6 | + def teardown |
7 | + Thread.current[:enabled_plugins] = nil | ||
8 | end | 8 | end |
9 | 9 | ||
10 | def test_identifier_validation | 10 | def test_identifier_validation |
@@ -1833,6 +1833,37 @@ class ProfileTest < ActiveSupport::TestCase | @@ -1833,6 +1833,37 @@ class ProfileTest < ActiveSupport::TestCase | ||
1833 | assert_equal [], profile.activities | 1833 | assert_equal [], profile.activities |
1834 | end | 1834 | end |
1835 | 1835 | ||
1836 | + should 'merge members of plugins to original members' do | ||
1837 | + original_community = fast_create(Community) | ||
1838 | + community1 = fast_create(Community, :identifier => 'community1') | ||
1839 | + community2 = fast_create(Community, :identifier => 'community2') | ||
1840 | + original_member = fast_create(Person) | ||
1841 | + plugin1_member = fast_create(Person) | ||
1842 | + plugin2_member = fast_create(Person) | ||
1843 | + original_community.add_member(original_member) | ||
1844 | + community1.add_member(plugin1_member) | ||
1845 | + community2.add_member(plugin2_member) | ||
1846 | + | ||
1847 | + class Plugin1 < Noosfero::Plugin | ||
1848 | + def organization_members(profile) | ||
1849 | + Person.members_of(Community.find_by_identifier('community1')) | ||
1850 | + end | ||
1851 | + end | ||
1852 | + | ||
1853 | + class Plugin2 < Noosfero::Plugin | ||
1854 | + def organization_members(profile) | ||
1855 | + Person.members_of(Community.find_by_identifier('community2')) | ||
1856 | + end | ||
1857 | + end | ||
1858 | + | ||
1859 | + original_community.stubs(:enabled_plugins).returns([Plugin1.new, Plugin2.new]) | ||
1860 | + | ||
1861 | + assert_includes original_community.members, original_member | ||
1862 | + assert_includes original_community.members, plugin1_member | ||
1863 | + assert_includes original_community.members, plugin2_member | ||
1864 | + assert 3, original_community.members.count | ||
1865 | + end | ||
1866 | + | ||
1836 | private | 1867 | private |
1837 | 1868 | ||
1838 | def assert_invalid_identifier(id) | 1869 | def assert_invalid_identifier(id) |
vendor/plugins/monkey_patches/methods_from_fake_arel/init.rb
0 → 100644
@@ -0,0 +1,71 @@ | @@ -0,0 +1,71 @@ | ||
1 | +# monkey patch to add fake_arel select, or_scope and where methods | ||
2 | +# this gem requires activesupport-2.3.14 and activerecord-2.3.14 | ||
3 | +# | ||
4 | +# https://github.com/gammons/fake_arel | ||
5 | + | ||
6 | +module Rails3Finder | ||
7 | + def self.included(base) | ||
8 | + base.class_eval do | ||
9 | + | ||
10 | + # the default named scopes | ||
11 | + named_scope :offset, lambda {|offset| {:offset => offset}} | ||
12 | + named_scope :limit, lambda {|limit| {:limit => limit}} | ||
13 | + named_scope :includes, lambda { |*includes| { :include => includes }} | ||
14 | + named_scope :order, lambda {|*order| {:order => order.join(',') }} | ||
15 | + named_scope :joins, lambda {|*join| {:joins => join } if join[0]} | ||
16 | + named_scope :from, lambda {|*from| {:from => from }} | ||
17 | + named_scope :having, lambda {|*having| {:having => having }} | ||
18 | + named_scope :group, lambda {|*group| {:group => group.join(',') }} | ||
19 | + named_scope :readonly, lambda {|readonly| {:readonly => readonly }} | ||
20 | + named_scope :lock, lambda {|lock| {:lock => lock }} | ||
21 | + | ||
22 | + def self.select(value = Proc.new) | ||
23 | + if block_given? | ||
24 | + all.select {|*block_args| value.call(*block_args) } | ||
25 | + else | ||
26 | + self.scoped(:select => Array.wrap(value).join(',')) | ||
27 | + end | ||
28 | + end | ||
29 | + | ||
30 | + __where_fn = lambda do |*where| | ||
31 | + if where.is_a?(Array) and where.size == 1 | ||
32 | + {:conditions => where.first} | ||
33 | + else | ||
34 | + {:conditions => where} | ||
35 | + end | ||
36 | + end | ||
37 | + | ||
38 | + named_scope :where, __where_fn | ||
39 | + | ||
40 | + # Use carefully this method! It might get lost with different classes | ||
41 | + # scopes or different types of joins. | ||
42 | + def self.or_scope(*scopes) | ||
43 | + where = [] | ||
44 | + joins = [] | ||
45 | + includes = [] | ||
46 | + | ||
47 | + # for some reason, flatten is actually executing the scope | ||
48 | + scopes = scopes[0] if scopes.size == 1 | ||
49 | + scopes.each do |s| | ||
50 | + s = s.proxy_options | ||
51 | + begin | ||
52 | + where << merge_conditions(s[:conditions]) | ||
53 | + rescue NoMethodError | ||
54 | + # I am ActiveRecord::Base. Only my subclasses define merge_conditions: | ||
55 | + where << subclasses.first.merge_conditions(s[:conditions]) | ||
56 | + end | ||
57 | + #where << merge_conditions(s[:conditions]) | ||
58 | + joins << s[:joins] unless s[:joins].nil? | ||
59 | + includes << s[:include] unless s[:include].nil? | ||
60 | + end | ||
61 | + scoped = self | ||
62 | + scoped = scoped.select("DISTINCT #{self.table_name}.*") | ||
63 | + scoped = scoped.includes(includes.uniq.flatten) unless includes.blank? | ||
64 | + scoped = scoped.joins(joins.uniq.flatten) unless joins.blank? | ||
65 | + scoped.where(where.join(" OR ")) | ||
66 | + end | ||
67 | + end | ||
68 | + end | ||
69 | +end | ||
70 | + | ||
71 | +ActiveRecord::Base.send :include, Rails3Finder |