Commit 4b01e9daf93043a619c73a863b445b4ba4adb104

Authored by Joenio Costa
2 parents b9d5a64e 11901a70

Merge remote-tracking branch 'danielbucher/sub_organizations_improvements' into …

…sub_organizations_improvements
Showing 27 changed files with 822 additions and 35 deletions   Show diff stats
app/models/person.rb
... ... @@ -43,7 +43,12 @@ class Person < Profile
43 43 alias_method_chain :has_permission?, :plugins
44 44  
45 45 def memberships
46   - Profile.memberships_of(self)
  46 + scopes = []
  47 + plugins_scopes = plugins.dispatch_scopes(:person_memberships, self)
  48 + scopes = plugins_scopes unless plugins_scopes.first.blank?
  49 + scopes << Profile.memberships_of(self)
  50 + return scopes.first if scopes.size == 1
  51 + ScopeTool.union *scopes
47 52 end
48 53  
49 54 def memberships_by_role(role)
... ...
app/models/profile.rb
... ... @@ -84,7 +84,8 @@ class Profile &lt; ActiveRecord::Base
84 84 def members
85 85 scopes = plugins.dispatch_scopes(:organization_members, self)
86 86 scopes << Person.members_of(self)
87   - scopes.size == 1 ? scopes.first : Person.or_scope(scopes)
  87 + return scopes.first if scopes.size == 1
  88 + ScopeTool.union *scopes
88 89 end
89 90  
90 91 def members_count
... ...
features/step_definitions/sub_organizations_block_steps.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +Given /^"([^\"]*)" is a sub organization of "([^\"]*)"$/ do |child, parent|
  2 + child = Organization.find_by_name(child) || Organization[child]
  3 + parent = Organization.find_by_name(parent) || Organization[parent]
  4 +
  5 + SubOrganizationsPlugin::Relation.add_children(parent, child)
  6 +end
... ...
features/support/paths.rb
... ... @@ -114,6 +114,13 @@ module NavigationHelpers
114 114 when /^(.+)'s members page/
115 115 '/profile/%s/members' % profile_identifier($1)
116 116  
  117 + when /^(.+)'s "(.+)" page from "(.*)" of "(.*)" plugin/
  118 + profile = $1
  119 + action = $2
  120 + plugin_name = $4.underscore
  121 + controller_type = $3.constantize.superclass.to_s.underscore.gsub(/_controller/, "")
  122 + "/#{controller_type}/#{profile}/plugin/#{plugin_name}/#{action}"
  123 +
117 124 else
118 125 begin
119 126 page_name =~ /the (.*) page/
... ...
lib/noosfero/plugin.rb
... ... @@ -372,6 +372,13 @@ class Noosfero::Plugin
372 372 nil
373 373 end
374 374  
  375 + # -> Extends person memberships list
  376 + # returns = An instance of ActiveRecord::NamedScope::Scope retrived through
  377 + # Person.memberships_of method.
  378 + def person_memberships(person)
  379 + nil
  380 + end
  381 +
375 382 # -> Extends person permission access
376 383 # returns = boolean
377 384 def has_permission?(person, permission, target)
... ...
lib/scope_tool.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +module ScopeTool
  2 +
  3 + # Sum scope results by SQL, allowing post filtering of the group.
  4 + def union(*scopes)
  5 + model = scopes.first.class_name.constantize
  6 + scopes = scopes.map &:to_sql
  7 + model.from "(\n#{scopes.join("\nUNION\n")}\n) as #{model.table_name}"
  8 + end
  9 +
  10 + class << self
  11 + # Allows to use `ScopeTool.method()` anywhere.
  12 + include ScopeTool
  13 + end
  14 +
  15 +end
... ...
plugins/sub_organizations/controllers/sub_organizations_plugin_profile_controller.rb 0 → 100644
... ... @@ -0,0 +1,45 @@
  1 +class SubOrganizationsPluginProfileController < ProfileController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + before_filter :organizations_only
  5 +
  6 + def children
  7 + children = SubOrganizationsPlugin::Relation.children(profile)
  8 + family_relation(children)
  9 + render 'related_organizations'
  10 + end
  11 +
  12 + def parents
  13 + parents = SubOrganizationsPlugin::Relation.parents(profile)
  14 + family_relation(parents)
  15 + render 'related_organizations'
  16 + end
  17 +
  18 + private
  19 +
  20 + def family_relation(_profile)
  21 + @communities = _profile.communities
  22 + @enterprises = _profile.enterprises
  23 + @full = true
  24 +
  25 + if !params[:type] and !params[:display]
  26 + @communities = SubOrganizationsPlugin.limit(@communities)
  27 + @enterprises = SubOrganizationsPlugin.limit(@enterprises)
  28 + @full = false
  29 + elsif !params[:type]
  30 + @total = _profile
  31 + @total = @total.paginate(:per_page => 2, :page => params[:npage])
  32 + if params[:display] == 'compact'
  33 + @full = false
  34 + end
  35 + else
  36 + @communities = @communities.paginate(:per_page => 2, :page => params[:npage])
  37 + @enterprises = @enterprises.paginate(:per_page => 2, :page => params[:npage])
  38 + end
  39 + end
  40 +
  41 + def organizations_only
  42 + render_not_found if !profile.organization?
  43 + end
  44 +
  45 +end
... ...
plugins/sub_organizations/features/sub_organizations_block.feature 0 → 100644
... ... @@ -0,0 +1,62 @@
  1 +Feature: related_organizations_block
  2 + As a user
  3 + I want my organizations to have blocks that lists it's related-organizations
  4 + In order to have quick access to it's related-organizations
  5 +
  6 + Background:
  7 + Given "SubOrganizations" plugin is enabled
  8 + And the following users
  9 + | login | name |
  10 + | homer | Homer |
  11 + And the following community
  12 + | identifier | name | owner |
  13 + | springfield | Springfield | homer |
  14 + | moe | Moe's | homer |
  15 + And the following enterprise
  16 + | identifier | name | owner |
  17 + | duff | Duff | homer |
  18 + And "moe" is a sub organization of "springfield"
  19 + And "duff" is a sub organization of "springfield"
  20 + And I am logged in as "homer"
  21 + And I go to springfield's control panel
  22 +
  23 + Scenario: display sub organizations block add option
  24 + When I follow "Edit sideboxes"
  25 + And I follow "Add a block"
  26 + Then I should see "Related Organizations"
  27 +
  28 + Scenario: display both sub types on block
  29 + When I follow "Edit sideboxes"
  30 + And I follow "Add a block"
  31 + And I choose "Related Organizations"
  32 + And I press "Add"
  33 + Then I should see "Moe's" within ".related-organizations-block"
  34 + And I should see "Duff" within ".related-organizations-block"
  35 +
  36 + Scenario: display only sub-communities
  37 + Given the following blocks
  38 + | owner | type |
  39 + | springfield | RelatedOrganizationsBlock |
  40 + When I follow "Edit sideboxes"
  41 + And I follow "Edit" within ".related-organizations-block"
  42 + And I select "Community" from "block_organization_type"
  43 + And I press "Save"
  44 + Then I should see "Moe's" within ".related-organizations-block"
  45 + And I should not see "Duff" within ".related-organizations-block"
  46 +
  47 + Scenario: display both sub types on sub-organizations page
  48 + When I go to springfield's "children" page from "SubOrganizationsPluginProfileController" of "SubOrganizations" plugin
  49 + Then I should see "Moe's"
  50 + And I should see "Duff"
  51 +
  52 + Scenario: display only sub-communities on sub-organizations page
  53 + Given the following blocks
  54 + | owner | type |
  55 + | springfield | RelatedOrganizationsBlock |
  56 + When I follow "Edit sideboxes"
  57 + And I follow "Edit" within ".related-organizations-block"
  58 + And I select "Community" from "block_organization_type"
  59 + And I press "Save"
  60 + And I follow "View all" within ".related-organizations-block"
  61 + Then I should see "Moe's" within ".profile-list"
  62 + And I should not see "Duff" within ".profile-list"
... ...
plugins/sub_organizations/features/sub_organizations_display.feature 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +Feature: sub_organizations_display
  2 + As a user
  3 + I want my organizations to have blocks that lists it's related-organizations
  4 + In order to have quick access to it's related-organizations
  5 +
  6 + Background:
  7 + Given "SubOrganizations" plugin is enabled
  8 + And the following users
  9 + | login | name |
  10 + | nelson | Nelson |
  11 + And feature "enterprise_registration" is enabled on environment
  12 + And the following community
  13 + | identifier | name | owner | description | city | state |
  14 + | springfield | Springfield | nelson | Springfield description | Los Angeles | California |
  15 + | moe | Moe | nelson | Moe description | Kansas | Texas |
  16 + And the following enterprise
  17 + | identifier | name | owner | description | city | state |
  18 + | school | School | nelson | School description | Terra do Nunca | Billy Jean |
  19 + And I am logged in as "nelson"
  20 + And I go to springfield's control panel
  21 + When I follow "Edit sideboxes"
  22 + And I follow "Add a block"
  23 + And I choose "Related Organizations"
  24 + And I press "Add"
  25 +
  26 + @selenium
  27 + Scenario: Display the sub organization block when there is a sub enterprise and communitys
  28 + When I go to springfield's control panel
  29 + And I follow "Manage sub-groups"
  30 + And I follow "Register a new sub-enterprise"
  31 + And I fill in "Name" with "Bart"
  32 + And I press "Next"
  33 + Then I should see "Enterprise registration completed"
  34 + And I am logged in as admin
  35 + And I go to admin_user's control panel
  36 + When I follow "Tasks" within ".control-panel"
  37 + Then I should see "Nelson wants to create enterprise Bart."
  38 + And the first mail is to admin_user@example.com
  39 + And I choose "Accept"
  40 + And I press "Apply!"
  41 + And I am logged in as "nelson"
  42 + When I go to springfield's control panel
  43 + And I follow "Manage sub-groups"
  44 + And I follow "Create a new sub-community"
  45 + And I fill in "Name" with "Homer"
  46 + And I press "Create"
  47 + When I go to springfield's "children" page from "SubOrganizationsPluginProfileController" of "SubOrganizations" plugin
  48 + Then I should see "Homer" within ".related-organizations-block"
  49 + And I should see "Bart" within ".related-organizations-block"
  50 +
  51 + Scenario: Display with compact mode
  52 + Given "moe" is a sub organization of "springfield"
  53 + And "school" is a sub organization of "springfield"
  54 + When I go to springfield's homepage
  55 + And I follow "View all" within ".related-organizations-block"
  56 + Then I should see "Springfield's sub-communities"
  57 + And I should see "Springfield's sub-enterprises"
  58 +
  59 + Scenario: Display with full mode for sub-communities
  60 + Given "moe" is a sub organization of "springfield"
  61 + When I go to springfield's homepage
  62 + And I follow "View all" within ".related-organizations-block"
  63 + Then I should see "Springfield's sub-communities"
  64 + And I follow "Full" within ".search-customize-options"
  65 + Then I should see "Moe description" within ".related-organizations-description"
  66 + And I should see "Kansas, Texas" within ".related-organizations-region-name"
  67 +
  68 + Scenario: Display with full mode for sub-enterprises
  69 + Given "school" is a sub organization of "springfield"
  70 + When I go to springfield's homepage
  71 + And I follow "View all" within ".related-organizations-block"
  72 + And I should see "Springfield's sub-enterprises"
  73 + And I follow "Full" within ".search-customize-options"
  74 + Then I should see "School description" within ".related-organizations-description"
  75 + And I should see "Terra do Nunca, Billy Jean" within ".related-organizations-region-name"
  76 +
  77 + Scenario: Display message when display full block are empty
  78 + Given I follow "View all" within ".related-organizations-block"
  79 + Then I should see "There are no sub-communities yet."
  80 + And I should see "There are no sub-enterprises yet."
... ...
plugins/sub_organizations/lib/related_organizations_block.rb 0 → 100644
... ... @@ -0,0 +1,60 @@
  1 +class RelatedOrganizationsBlock < ProfileListBlock
  2 +
  3 + settings_items :organization_type, :type => :string, :default => 'both'
  4 +
  5 + @display_type = {:title => 'related', :action => 'children' }
  6 +
  7 + def self.description
  8 + __("#{@display_type[:title].capitalize} Organizations")
  9 + end
  10 +
  11 + def default_title
  12 + case organization_type
  13 + when 'enterprise'
  14 + n__("{#} #{@display_type[:title]} enterprise", "{#} #{@display_type[:title]} enterprises", profile_count)
  15 + when 'community'
  16 + n__("{#} #{@display_type[:title]} community", "{#} #{@display_type[:title]} communities", profile_count)
  17 + else
  18 + n__("{#} #{@display_type[:title]} organization", "{#} #{@display_type[:title]} organizations", profile_count)
  19 + end
  20 + end
  21 +
  22 + def help
  23 + _("This block displays #{@display_type[:title]} organizations of this organization")
  24 + end
  25 +
  26 + def profiles
  27 + organizations = related_organizations
  28 + case organization_type
  29 + when 'enterprise'
  30 + organizations.enterprises
  31 + when 'community'
  32 + organizations.communities
  33 + else
  34 + organizations
  35 + end
  36 + end
  37 +
  38 + def footer
  39 + profile = self.owner
  40 + type = self.organization_type
  41 + params = {:profile => profile.identifier, :controller => 'sub_organizations_plugin_profile', :action => @display_type[:action]}
  42 + params[:type] = type if type == 'enterprise' || type == 'community'
  43 + lambda do
  44 + link_to _('View all'), params.merge(params)
  45 + end
  46 + end
  47 +
  48 + def related_organizations
  49 + profile = self.owner
  50 + organizations = SubOrganizationsPlugin::Relation.parents(profile)
  51 +
  52 + if organizations.blank?
  53 + @display_type = {:title => 'sub', :action => 'children'}
  54 + organizations = SubOrganizationsPlugin::Relation.children(profile)
  55 + else
  56 + @display_type = {:title => 'parent', :action => 'parents' }
  57 + organizations
  58 + end
  59 + end
  60 +end
... ...
plugins/sub_organizations/lib/sub_organizations_plugin.rb
  1 +require_dependency File.dirname(__FILE__) + '/related_organizations_block'
  2 +
  3 +class SubOrganizationsPlugin < Noosfero::Plugin; end;
  4 +
  5 +require_dependency 'sub_organizations_plugin/search_helper'
  6 +
1 7 class SubOrganizationsPlugin < Noosfero::Plugin
2 8  
  9 + include SearchHelper
  10 +
  11 + DISPLAY_LIMIT = 12
  12 +
3 13 def self.plugin_name
4 14 _("Sub-groups")
5 15 end
... ... @@ -23,6 +33,10 @@ class SubOrganizationsPlugin &lt; Noosfero::Plugin
23 33 Person.members_of(children) if children.present?
24 34 end
25 35  
  36 + def person_memberships(person)
  37 + SubOrganizationsPlugin::Relation.parents(*Profile.memberships_of(person))
  38 + end
  39 +
26 40 def has_permission?(person, permission, target)
27 41 if !target.kind_of?(Environment) && target.organization?
28 42 SubOrganizationsPlugin::Relation.parents(target).map do |parent|
... ... @@ -40,4 +54,14 @@ class SubOrganizationsPlugin &lt; Noosfero::Plugin
40 54 parent_to_be = context.params[:sub_organizations_plugin_parent_to_be]
41 55 {'sub_organizations_plugin_parent_to_be' => parent_to_be} if parent_to_be.present?
42 56 end
  57 +
  58 + def self.limit(organizations)
  59 + organizations.all(:limit => DISPLAY_LIMIT, :order => 'updated_at DESC').sort_by{ rand }
  60 + end
  61 +
  62 + def self.extra_blocks
  63 + {
  64 + RelatedOrganizationsBlock => {:type => [Enterprise, Community], :position => ['1', '2', '3']}
  65 + }
  66 + end
43 67 end
... ...
plugins/sub_organizations/lib/sub_organizations_plugin/relation.rb
... ... @@ -33,11 +33,11 @@ class SubOrganizationsPlugin::Relation &lt; Noosfero::Plugin::ActiveRecord
33 33 ActiveRecord::NamedScope::Scope.new(Organization, options)
34 34 end
35 35  
36   - def parents(child)
  36 + def parents(*children)
37 37 options = {
38 38 :select => "profiles.*",
39 39 :joins => "inner join sub_organizations_plugin_relations as relations on profiles.id=relations.parent_id",
40   - :conditions => ["relations.child_id = ?", child.id]
  40 + :conditions => ["relations.child_id in (?)", children.map(&:id)]
41 41 }
42 42 ActiveRecord::NamedScope::Scope.new(Organization, options)
43 43 end
... ...
plugins/sub_organizations/lib/sub_organizations_plugin/relation_helper.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +module SubOrganizationsPlugin::RelationHelper
  2 + def display_relation(organization,type,display_mode)
  3 + if display_mode == 'full'
  4 + render :partial => 'sub_organizations_plugin_profile/full_related_organizations', :locals => {:organizations => organization,:organization_type => type}
  5 + else
  6 + render :partial => 'sub_organizations_plugin_profile/related_organizations', :locals => {:organizations => organization, :organization_type => type}
  7 + end
  8 + end
  9 +end
0 10 \ No newline at end of file
... ...
plugins/sub_organizations/lib/sub_organizations_plugin/search_helper.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +require_dependency 'search_helper'
  2 +
  3 +module SubOrganizationsPlugin::SearchHelper
  4 +
  5 + include SearchHelper
  6 +
  7 + def display_selectors(display, float = 'right')
  8 + display = 'compact' if display.blank?
  9 + compact_link = display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))
  10 + full_link = display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))
  11 + content_tag('div',
  12 + content_tag('strong', _('Display')) + ': ' + [compact_link,full_link].compact.join(' | ').html_safe,
  13 + :class => 'search-customize-options'
  14 + )
  15 + end
  16 +
  17 +
  18 +end
... ...
plugins/sub_organizations/public/images/arrow-right-p.png 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../../../public/designs/themes/base/imgs/arrow-right-p.png
0 2 \ No newline at end of file
... ...
plugins/sub_organizations/public/style.css
1 1 #content .token-input-list {
2 2 margin-bottom: 30px;
3 3 }
  4 +
  5 +.related-organizations-button-bar {
  6 + padding-top: 40px;
  7 + clear: both;
  8 +}
  9 +
  10 +.related-organizations-block .block-footer-content a {
  11 + position: absolute;
  12 + top: 2px;
  13 + right: 0px;
  14 + font-size: 11px;
  15 + color: #000;
  16 + text-decoration: none;
  17 + padding-right: 15px;
  18 + background: url(images/arrow-right-p.png) 100% 50% no-repeat;
  19 +}
  20 +
  21 +.clearfix {
  22 + clear: both;
  23 +}
  24 +
  25 +.related-organizations-list-block .vcard{
  26 + margin-right: 10px;
  27 + -webkit-border-radius: 0 !important;
  28 + -moz-border-radius: 0!important;
  29 + -o-border-radius: 0!important;
  30 + border-radius: 0!important;
  31 +}
  32 +.related-organizations-item-column-right .search-result-title{
  33 + margin: 10px 0;
  34 +}
  35 +
  36 +#main-content-wrapper-8 ul{
  37 + padding-left: 0;
  38 +}
  39 +
  40 +.related-organizations-list-block ul li{
  41 + list-style: none;
  42 + margin: 10px 0;
  43 + border: 1px solid #ccc;
  44 + /*padding: 10px 5px;*/
  45 +}
  46 +
  47 +.related-organizations-list-block ul li:hover{
  48 + border: 1px solid #999;
  49 +}
  50 +
  51 +.related-organizations-list-block .profile_link{
  52 + height: auto !important;
  53 + max-height: none !important;
  54 + max-width: none !important;
  55 + height: 150px;
  56 + width: 150px;
  57 +}
  58 +
  59 +.related-organizations-list-block .org {
  60 + display: none !important;
  61 +}
  62 +
  63 +.related-organizations-item .profile-image img{
  64 + max-height: 150px;
  65 + max-width: 150px;
  66 +}
  67 +
  68 +
  69 +.menu-submenu-list>li{
  70 + border: 0!important;
  71 +}
  72 +
  73 +.related-organizations-list-block .menu-submenu{
  74 + bottom: 147px;
  75 + right: 5px;
  76 +}
  77 +
  78 +.related-organizations-region-name{
  79 + line-height: 2em;
  80 + font-weight: bold;
  81 +}
  82 +
  83 +.related-organizations-description{
  84 + color: #333;
  85 +}
  86 +
  87 +
  88 +.related-organizations-list-block .vcard a{
  89 + padding: 0;
  90 + margin: 0;
  91 + border: 0;
  92 +}
  93 +
  94 +.related-organizations-list-block .vcard img {
  95 + opacity: 1;
  96 + -webkit-transition: all 0.5s ease-out;
  97 + -moz-transition: all 0.5s ease-out;
  98 + -o-transition: all 0.5s ease-out;
  99 + -ms-transition: all 0.5s ease-out;
  100 + transition: all 0.5s ease-out;
  101 +}
  102 +
  103 +.related-organizations-list-block .vcard img:hover {
  104 + opacity: 0.5;
  105 +}
  106 +
  107 +.related-organizations-item-column-right {
  108 + float: right;
  109 + position: relative;
  110 + width: 65%;
  111 +}
  112 +
  113 +.related-organizations-item-column-left {
  114 +float: left;
  115 +position: relative;
  116 +width: 35%;
  117 +}
  118 +
  119 +.related-organizations-block ul {
  120 + min-width: 196px;
  121 + width: 192px;
  122 + margin: 0px 0px 0px -3px;
  123 + padding: 0px;
  124 +}
... ...
plugins/sub_organizations/test/functional/sub_organizations_plugin_profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,59 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/sub_organizations_plugin_profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class SubOrganizationsPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class SubOrganizationsPluginProfileControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = SubOrganizationsPluginProfileController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 + @organization = Organization.create!(:name => 'My Organization', :identifier => 'my-organization')
  14 + @person = create_user('person').person
  15 + @organization.add_admin(@person)
  16 + login_as(@person.user.login)
  17 + e = Environment.default
  18 + e.enable_plugin('SubOrganizationsPlugin')
  19 + e.save!
  20 + @o1 = fast_create(Organization, :name => 'sample child organization 1')
  21 + @o2 = fast_create(Community, :name => 'sample child community 1')
  22 + @o3 = fast_create(Enterprise, :name => 'sample child enterprise 1')
  23 +
  24 + SubOrganizationsPlugin::Relation.add_children(@organization, @o2, @o3)
  25 + end
  26 +
  27 + attr_accessor :person, :organization
  28 +
  29 + should 'display all children organizations' do
  30 + get :children, :profile => @organization.identifier
  31 +
  32 + assert_no_match /#{@o1.name}/, @response.body
  33 + assert_match /#{@o2.name}/, @response.body
  34 + assert_match /#{@o3.name}/, @response.body
  35 + end
  36 +
  37 + should 'display only communities' do
  38 + get :children, :profile => @organization.identifier, :type => 'community'
  39 +
  40 + assert_no_match /#{@o1.name}/, @response.body
  41 + assert_match /#{@o2.name}/, @response.body
  42 + assert_no_match /#{@o3.name}/, @response.body
  43 + end
  44 +
  45 + should 'display only enterprises' do
  46 + get :children, :profile => @organization.identifier, :type => 'enterprise'
  47 +
  48 + assert_no_match /#{@o1.name}/, @response.body
  49 + assert_no_match /#{@o2.name}/, @response.body
  50 + assert_match /#{@o3.name}/, @response.body
  51 + end
  52 +
  53 + should 'not respond to person profiles' do
  54 + get :children, :profile => fast_create(Person, :name => 'Ze').identifier
  55 +
  56 + assert_response :missing
  57 + end
  58 +
  59 +end
... ...
plugins/sub_organizations/test/unit/related_organizations_block_test.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../lib/related_organizations_block'
  3 +
  4 +class RelatedOrganizationsBlockTest < ActiveSupport::TestCase
  5 +
  6 + def setup
  7 + @block = RelatedOrganizationsBlock.new
  8 + end
  9 +
  10 + attr_reader :block
  11 +
  12 + should 'have both as default organization_type' do
  13 + assert_equal "both", block.organization_type
  14 + end
  15 +
  16 + should 'return only children when the organization is a parent' do
  17 + parent = fast_create(Organization, :name => 'I am your father', :identifier => 'i-am-your-father')
  18 + child1 = fast_create(Organization, :name => 'Rebel Alliance')
  19 + child2 = fast_create(Organization, :name => 'The Empire')
  20 + org1 = fast_create(Organization, :name => 'Jedi Council')
  21 + box = fast_create(Box, :owner_id => parent.id, :owner_type => 'Organization')
  22 + @block.box = box
  23 + @block.save!
  24 + SubOrganizationsPlugin::Relation.add_children(parent, child1, child2)
  25 +
  26 + assert @block.related_organizations.include?(child1)
  27 + assert @block.related_organizations.include?(child2)
  28 + assert !@block.related_organizations.include?(org1)
  29 + end
  30 +end
... ...
plugins/sub_organizations/test/unit/sub_organizations_plugin_test.rb
... ... @@ -45,6 +45,35 @@ class SubOrganizationsTest &lt; ActiveSupport::TestCase
45 45 assert org3_members.blank?
46 46 end
47 47  
  48 + should 'include parent-organizations in persons memberships' do
  49 + org1 = fast_create(Organization)
  50 + org2 = fast_create(Organization)
  51 + org3 = fast_create(Organization)
  52 + person1 = fast_create(Person)
  53 + person2 = fast_create(Person)
  54 + org1.add_member(person2)
  55 + org2.add_member(person1)
  56 + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2)
  57 + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org3)
  58 +
  59 + person1_memberships = plugin.person_memberships(person1)
  60 + person2_memberships = plugin.person_memberships(person2)
  61 +
  62 + assert_equal ActiveRecord::NamedScope::Scope, person1_memberships.class
  63 + assert_includes person1_memberships, org1
  64 + assert_not_includes person1_memberships, org2
  65 + assert_not_includes person1_memberships, org3
  66 + assert person2_memberships.blank?
  67 + end
  68 +
  69 + should 'return blank for person memberships with no organization ' do
  70 + person1 = fast_create(Person)
  71 +
  72 + person1_memberships = plugin.person_memberships(person1)
  73 +
  74 + assert person1_memberships.blank?
  75 + end
  76 +
48 77 should 'grant permission that user has on parent organizations over children orgnaizations' do
49 78 person = create_user('admin-user').person
50 79 org1 = fast_create(Organization)
... ...
plugins/sub_organizations/views/box_organizer/_related_organizations_block.rhtml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +<div id='edit-related-organizations-block'>
  2 + <label for="block_organization_type"><%= _('Type of organizations to be displayed') %></label><br/>
  3 + <%= select_tag('block[organization_type]', options_for_select([[_('Both'), 'both'], [_('Community'), 'community'], [_('Enterprise'), 'enterprise']], @block.organization_type)) %>
  4 + <%= labelled_form_field _('Limit of items'), text_field(:block, :limit, :size => 3) %>
  5 + <%= check_box(:block, :prioritize_profiles_with_image) %>
  6 + <label for="block_prioritize_profiles_with_image"><%= _('Prioritize profiles with image') %></label>
  7 +</div>
... ...
plugins/sub_organizations/views/profile_design 0 → 120000
... ... @@ -0,0 +1 @@
  1 +box_organizer/
0 2 \ No newline at end of file
... ...
plugins/sub_organizations/views/sub_organizations_plugin_profile/_full_related_organizations.rhtml 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +<% extend SubOrganizationsPlugin::SearchHelper %>
  2 +<div class="related-organizations-list-block">
  3 +
  4 + <h1><%= __("#{profile.name}'s sub-#{organization_type.pluralize}") %></h1>
  5 + <ul>
  6 + <% organizations.each do |organization| %>
  7 + <li class="related-organizations-item">
  8 + <div class="related-organizations-item">
  9 + <div class="related-organizations-item-column-left">
  10 + <%= profile_image_link organization, :big, 'div' %>
  11 + </div>
  12 + <div class="related-organizations-item-column-right">
  13 + <%= link_to_homepage(organization.name, organization.identifier, :class => "search-result-title") %>
  14 + <div class="related-organizations-description">
  15 + <% if organization.description %>
  16 + <% body_stripped = strip_tags(organization.description) %>
  17 + <% elsif organization.home_page and organization.home_page.body %>
  18 + <% body_stripped = strip_tags(organization.home_page.body) %>
  19 + <% end %>
  20 + <%= excerpt(body_stripped, body_stripped.first(3), 200) if body_stripped %>
  21 + </div>
  22 + <div class="related-organizations-region">
  23 + <span class="related-organizations-region-label"><%= _("City") %></span>
  24 + <% if organization.region %>
  25 + <span class="related-organizations-region-name"><%= city_with_state(organization.region) %></span>
  26 + <% elsif organization.city and organization.state %>
  27 + <span class="related-organizations-region-name"><%= "#{organization.city}, #{organization.state}" %></span>
  28 + <% end %>
  29 + </div>
  30 +
  31 + <div class="related-organizations-categorization">
  32 + <% organization.top_level_categorization.each do |parent, children| %>
  33 + <div class="related-organizations-category-<%=parent.id%> related-organizations-category">
  34 + <span class="related-organizations-categorization-parent"><%= parent.name %></span>
  35 + <span class="related-organizations-categorization-children">
  36 + <%= children.collect(&:name).join(', ') %>
  37 + </span>
  38 + </div>
  39 + <% end %>
  40 + </div>
  41 + </div>
  42 +
  43 + <br class="clearfix" />
  44 +
  45 + </div>
  46 + </li>
  47 + <% end %>
  48 + </ul>
  49 +
  50 + <div id='pagination-related-organizations'>
  51 + <%= pagination_links(organizations, {:param_name => 'npage', :page_links => true}) %>
  52 + </div>
  53 +
  54 + <% button_bar(:class => "related-organizations-button-bar") do %>
  55 + <%= button :back, _('Go back'), { :controller => 'profile' } %>
  56 + <%= button :add, __("Add a new #{organization_type}"), :controller => 'sub_organizations_plugin_myprofile', :action => 'index' if logged_in? && user.has_permission?(:edit_profile, profile) && !environment.enabled?("disable_asset_#{organization_type.pluralize}") %>
  57 +
  58 + <% if !@full %>
  59 + <%= button :more, _('View all'), { :controller => 'sub_organizations_plugin_profile', :action => params[:action], :type => organization_type } %>
  60 + <% end %>
  61 + <% end %>
  62 +
  63 +</div>
... ...
plugins/sub_organizations/views/sub_organizations_plugin_profile/_related_organizations.rhtml 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +<% extend SubOrganizationsPlugin::ApplicationHelper %>
  2 +<div class="common-profile-list-block">
  3 + <h1><%= __("#{profile.name}'s sub-#{organization_type.pluralize}") %></h1>
  4 +
  5 + <ul class='profile-list'>
  6 + <% organizations.each do |organization| %>
  7 + <%= profile_image_link(organization)%>
  8 + <% end %>
  9 + </ul>
  10 + <% if organizations.length == 0 %>
  11 + <li><%= __("There are no sub-#{organization_type.pluralize} yet. " ) %></li>
  12 + <% end %>
  13 + <% button_bar(:class => "related-organizations-button-bar") do %>
  14 + <%= button :back, _('Go back'), { :controller => 'profile' } %>
  15 + <%= button :add, __("Add a new #{organization_type}"), :controller => 'sub_organizations_plugin_myprofile', :action => 'index' if logged_in? && user.has_permission?(:edit_profile, profile) && !environment.enabled?("disable_asset_#{organization_type.pluralize}") %>
  16 +
  17 + <% if !@full %>
  18 + <%= button :more, _('View all'), { :controller => 'sub_organizations_plugin_profile', :action => params[:action], :type => organization_type } %>
  19 + <% end %>
  20 + <% end %>
  21 +</div>
  22 +<% if @full %>
  23 + <div id='pagination-profiles'>
  24 + <%= pagination_links(organizations, {:param_name => 'npage', :page_links => true}) %>
  25 + </div>
  26 +<% end %>
  27 +<!-- fim class="common-profile-list-block" -->
... ...
plugins/sub_organizations/views/sub_organizations_plugin_profile/related_organizations.rhtml 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<% extend SubOrganizationsPlugin::SearchHelper %>
  2 +<% extend SubOrganizationsPlugin::RelationHelper %>
  3 +
  4 +<div id="search-actions">
  5 + <%= display_selectors(params[:display]) %>
  6 +</div>
  7 +
  8 +<% if params[:type] == 'community' %>
  9 + <%= display_relation(@communities,params[:type],params[:display]) %>
  10 +<% end %>
  11 +
  12 +<% if params[:type] == 'enterprise' %>
  13 + <%= display_relation(@enterprises,params[:type],params[:display]) %>
  14 +<% end %>
  15 +
  16 +<% if ["full"].include?(params[:display]) and !params[:type] %>
  17 + <%= display_relation(@total,"organizations",params[:display]) %>
  18 +<% elsif !params[:type] %>
  19 + <%= display_relation(@communities,"community",params[:display]) %>
  20 + <%= display_relation(@enterprises,"enterprise",params[:display]) %>
  21 +<% end %>
... ...
test/unit/person_test.rb
... ... @@ -1413,4 +1413,37 @@ class PersonTest &lt; ActiveSupport::TestCase
1413 1413 person.reload
1414 1414 assert_equal person.activities, []
1415 1415 end
  1416 +
  1417 + should 'merge memberships of plugins to original memberships' do
  1418 + class Plugin1 < Noosfero::Plugin
  1419 + def person_memberships(person)
  1420 + Profile.memberships_of(Person.find_by_identifier('person1'))
  1421 + end
  1422 + end
  1423 +
  1424 + class Plugin2 < Noosfero::Plugin
  1425 + def person_memberships(person)
  1426 + Profile.memberships_of(Person.find_by_identifier('person2'))
  1427 + end
  1428 + end
  1429 +
  1430 + Environment.default.enable_plugin(Plugin1)
  1431 + Environment.default.enable_plugin(Plugin2)
  1432 +
  1433 + original_person = fast_create(Person)
  1434 + person1 = fast_create(Person, :identifier => 'person1')
  1435 + person2 = fast_create(Person, :identifier => 'person2')
  1436 + original_cmm = fast_create(Community)
  1437 + plugin1_cmm = fast_create(Community)
  1438 + plugin2_cmm = fast_create(Community)
  1439 + original_cmm.add_member(original_person)
  1440 + plugin1_cmm.add_member(person1)
  1441 + plugin2_cmm.add_member(person2)
  1442 +
  1443 + assert_includes original_person.memberships, original_cmm
  1444 + assert_includes original_person.memberships, plugin1_cmm
  1445 + assert_includes original_person.memberships, plugin2_cmm
  1446 + assert 3, original_person.memberships.count
  1447 + end
  1448 +
1416 1449 end
... ...
test/unit/scope_tool.rb 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class ScopeToolTest < ActiveSupport::TestCase
  4 + include ScopeTool
  5 +
  6 + should 'unite scopes' do
  7 + cmm = fast_create Community
  8 + ent = fast_create Enterprise
  9 + orgs = union(Profile.communities, Profile.enterprises)
  10 + assert orgs.include? cmm
  11 + assert orgs.include? ent
  12 + end
  13 +
  14 + should 'filter united scopes' do
  15 + cmm1 = fast_create Community, :visible => true
  16 + cmm2 = fast_create Community, :visible => false
  17 + ent1 = fast_create Enterprise, :visible => true
  18 + ent2 = fast_create Enterprise, :visible => false
  19 + orgs = union(Profile.communities, Profile.enterprises)
  20 + assert orgs.include? cmm1
  21 + assert orgs.include? cmm2
  22 + assert orgs.include? ent1
  23 + assert orgs.include? ent2
  24 + orgs = orgs.visible
  25 + assert orgs.include? cmm1
  26 + assert !orgs.include?(cmm2)
  27 + assert orgs.include? ent1
  28 + assert !orgs.include?(ent2)
  29 + end
  30 +
  31 +end
... ...
vendor/plugins/monkey_patches/methods_from_fake_arel/init.rb
... ... @@ -19,14 +19,6 @@ module Rails3Finder
19 19 named_scope :readonly, lambda {|readonly| {:readonly => readonly }}
20 20 named_scope :lock, lambda {|lock| {:lock => lock }}
21 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 22 __where_fn = lambda do |*where|
31 23 if where.is_a?(Array) and where.size == 1
32 24 {:conditions => where.first}
... ... @@ -37,33 +29,66 @@ module Rails3Finder
37 29  
38 30 named_scope :where, __where_fn
39 31  
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 = []
  32 + class << self
46 33  
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])
  34 + def select(value = Proc.new)
  35 + if block_given?
  36 + all.select {|*block_args| value.call(*block_args) }
  37 + else
  38 + self.scoped(:select => Array.wrap(value).join(','))
56 39 end
57   - #where << merge_conditions(s[:conditions])
58   - joins << s[:joins] unless s[:joins].nil?
59   - includes << s[:include] unless s[:include].nil?
60 40 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 "))
  41 +
  42 + def to_sql
  43 + join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), nil), nil)
  44 + scope = scope(:find) || {}
  45 + options = current_scoped_methods || {}
  46 + sql = "SELECT #{(scope && scope[:select]) || default_select(options[:joins] || (scope && scope[:joins]))} "
  47 + sql << "FROM #{(scope && scope[:from]) || quoted_table_name} "
  48 + sql << join_dependency.join_associations.collect{|join| join.association_join }.join
  49 +
  50 + add_joins!(sql, options[:joins], scope)
  51 + add_conditions!(sql, options[:conditions], scope)
  52 + add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit])
  53 +
  54 + add_group!(sql, options[:group], options[:having], scope)
  55 + add_order!(sql, options[:order], scope)
  56 + add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections)
  57 + add_lock!(sql, options, scope)
  58 +
  59 + return sanitize_sql(sql)
  60 + end
  61 +
  62 + # Use carefully this method! It might get lost with different classes
  63 + # scopes or different types of joins.
  64 + def or_scope(*scopes)
  65 + where = []
  66 + joins = []
  67 + includes = []
  68 +
  69 + # for some reason, flatten is actually executing the scope
  70 + scopes = scopes[0] if scopes.size == 1
  71 + scopes.each do |s|
  72 + s = s.proxy_options
  73 + begin
  74 + where << merge_conditions(s[:conditions])
  75 + rescue NoMethodError
  76 + # I am ActiveRecord::Base. Only my subclasses define merge_conditions:
  77 + where << subclasses.first.merge_conditions(s[:conditions])
  78 + end
  79 + #where << merge_conditions(s[:conditions])
  80 + joins << s[:joins] unless s[:joins].nil?
  81 + includes << s[:include] unless s[:include].nil?
  82 + end
  83 + scoped = self
  84 + scoped = scoped.select("DISTINCT #{self.table_name}.*")
  85 + scoped = scoped.includes(includes.uniq.flatten) unless includes.blank?
  86 + scoped = scoped.joins(joins.uniq.flatten) unless joins.blank?
  87 + scoped.where(where.join(" OR "))
  88 + end
  89 +
66 90 end
  91 +
67 92 end
68 93 end
69 94 end
... ...