Commit f644224ed4f27658c1370dac099c76ecead439f3

Authored by Victor Costa
2 parents 2547177c 23636102

Merge branch 'master' into rails3

Conflicts:
	plugins/display_content/test/unit/display_content_block_test.rb
Showing 75 changed files with 1725 additions and 477 deletions   Show diff stats
app/controllers/admin/environment_design_controller.rb
... ... @@ -5,7 +5,7 @@ class EnvironmentDesignController < BoxOrganizerController
5 5 def available_blocks
6 6 # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
7 7 # the Noosfero core soon, see ActionItem3045
8   - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
  8 + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
9 9 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
10 10 end
11 11  
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -144,6 +144,7 @@ class CmsController < MyProfileController
144 144  
145 145 @article.profile = profile
146 146 @article.last_changed_by = user
  147 + @article.created_by = user
147 148  
148 149 translations if @article.translatable?
149 150  
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -9,14 +9,8 @@ class ProfileDesignController < BoxOrganizerController
9 9  
10 10 blocks += plugins.dispatch(:extra_blocks)
11 11  
12   - # blocks exclusive for organizations
13   - if profile.has_members?
14   - blocks << MembersBlock
15   - end
16   -
17 12 # blocks exclusive to people
18 13 if profile.person?
19   - blocks << FriendsBlock
20 14 blocks << FavoriteEnterprisesBlock
21 15 blocks << CommunitiesBlock
22 16 blocks << EnterprisesBlock
... ...
app/helpers/sweeper_helper.rb
... ... @@ -18,9 +18,7 @@ module SweeperHelper
18 18 expire_timeout_fragment(profile.manage_friends_cache_key(:npage => i.to_s))
19 19 end
20 20  
21   - # friends blocks
22   - blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)}
23   - BlockSweeper.expire_blocks(blocks)
  21 + expire_blocks_cache(profile, [:profile])
24 22 end
25 23  
26 24 def expire_communities(profile)
... ...
app/models/approve_article.rb
... ... @@ -48,7 +48,7 @@ class ApproveArticle &lt; Task
48 48 end
49 49  
50 50 def perform
51   - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author_id)
  51 + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.last_changed_by_id, :created_by_id => article.created_by_id)
52 52 end
53 53  
54 54 def title
... ...
app/models/article.rb
... ... @@ -40,12 +40,6 @@ class Article &lt; ActiveRecord::Base
40 40 # xss_terminate plugin can't sanitize array fields
41 41 before_save :sanitize_tag_list
42 42  
43   - before_create do |article|
44   - if article.last_changed_by_id
45   - article.author_name = Person.find(article.last_changed_by_id).name
46   - end
47   - end
48   -
49 43 belongs_to :profile
50 44 validates_presence_of :profile_id, :name
51 45 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? }
... ... @@ -55,6 +49,7 @@ class Article &lt; ActiveRecord::Base
55 49 validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
56 50  
57 51 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
  52 + belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id'
58 53  
59 54 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
60 55  
... ... @@ -89,6 +84,11 @@ class Article &lt; ActiveRecord::Base
89 84 article.parent = article.profile.blog
90 85 end
91 86 end
  87 +
  88 + if article.created_by
  89 + article.author_name = article.created_by.name
  90 + end
  91 +
92 92 end
93 93  
94 94 after_destroy :destroy_activity
... ... @@ -205,6 +205,10 @@ class Article &lt; ActiveRecord::Base
205 205 acts_as_versioned
206 206 self.non_versioned_columns << 'setting'
207 207  
  208 + def version_condition_met?
  209 + (['name', 'body', 'abstract', 'filename', 'start_date', 'end_date', 'image_id', 'license_id'] & changed).length > 0
  210 + end
  211 +
208 212 def comment_data
209 213 comments.map {|item| [item.title, item.body].join(' ') }.join(' ')
210 214 end
... ... @@ -630,17 +634,13 @@ class Article &lt; ActiveRecord::Base
630 634  
631 635 def author(version_number = nil)
632 636 if version_number
633   - version = versions.find_by_version(version_number)
  637 + version = self.versions.find_by_version(version_number)
634 638 author_id = version.last_changed_by_id if version
635   - Person.exists?(author_id) ? Person.find(author_id) : nil
636 639 else
637   - if versions.empty?
638   - last_changed_by
639   - else
640   - author_id = versions.first.last_changed_by_id
641   - Person.exists?(author_id) ? Person.find(author_id) : nil
642   - end
  640 + author_id = self.created_by_id
643 641 end
  642 +
  643 + environment.people.find_by_id(author_id)
644 644 end
645 645  
646 646 def author_name(version_number = nil)
... ...
app/models/box.rb
... ... @@ -34,14 +34,11 @@ class Box &lt; ActiveRecord::Base
34 34 FansBlock,
35 35 FavoriteEnterprisesBlock,
36 36 FeedReaderBlock,
37   - FriendsBlock,
38 37 HighlightsBlock,
39 38 LinkListBlock,
40 39 LoginBlock,
41 40 MainBlock,
42   - MembersBlock,
43 41 MyNetworkBlock,
44   - PeopleBlock,
45 42 ProfileImageBlock,
46 43 RawHTMLBlock,
47 44 RecentDocumentsBlock,
... ... @@ -63,14 +60,11 @@ class Box &lt; ActiveRecord::Base
63 60 FavoriteEnterprisesBlock,
64 61 FeaturedProductsBlock,
65 62 FeedReaderBlock,
66   - FriendsBlock,
67 63 HighlightsBlock,
68 64 LinkListBlock,
69 65 LocationBlock,
70 66 LoginBlock,
71   - MembersBlock,
72 67 MyNetworkBlock,
73   - PeopleBlock,
74 68 ProductsBlock,
75 69 ProductCategoriesBlock,
76 70 ProfileImageBlock,
... ...
app/models/community.rb
... ... @@ -85,10 +85,6 @@ class Community &lt; Organization
85 85 recent_documents(limit, ["articles.type != ? AND articles.highlighted = ?", 'Folder', highlight])
86 86 end
87 87  
88   - def blocks_to_expire_cache
89   - [MembersBlock]
90   - end
91   -
92 88 def each_member(offset=0)
93 89 while member = self.members.first(:order => :id, :offset => offset)
94 90 yield member
... ...
app/models/environment.rb
... ... @@ -182,7 +182,6 @@ class Environment &lt; ActiveRecord::Base
182 182  
183 183 # "right" area
184 184 env.boxes[2].blocks << CommunitiesBlock.new(:limit => 6)
185   - env.boxes[2].blocks << PeopleBlock.new(:limit => 6)
186 185 end
187 186  
188 187 # One Environment can be reached by many domains
... ...
app/models/friends_block.rb
... ... @@ -1,26 +0,0 @@
1   -class FriendsBlock < ProfileListBlock
2   -
3   - def self.description
4   - _('Friends')
5   - end
6   -
7   - def default_title
8   - n_('{#} friend', '{#} friends', profile_count)
9   - end
10   -
11   - def help
12   - _('This block displays your friends.')
13   - end
14   -
15   - def footer
16   - owner_id = owner.identifier
17   - proc do
18   - link_to s_('friends|View all'), :profile => owner_id, :controller => 'profile', :action => 'friends'
19   - end
20   - end
21   -
22   - def profiles
23   - owner.friends
24   - end
25   -
26   -end
app/models/members_block.rb
... ... @@ -1,52 +0,0 @@
1   -class MembersBlock < ProfileListBlock
2   - settings_items :show_join_leave_button, :type => :boolean, :default => false
3   -
4   - attr_accessible :show_join_leave_button
5   -
6   - def self.description
7   - _('Members')
8   - end
9   -
10   - def default_title
11   - _('{#} members')
12   - end
13   -
14   - def help
15   - _('This block presents the members of a collective.')
16   - end
17   -
18   - def footer
19   - profile = self.owner
20   - s = show_join_leave_button
21   -
22   - proc do
23   - render :file => 'blocks/members', :locals => { :profile => profile, :show_join_leave_button => s}
24   - end
25   - end
26   -
27   - def profiles
28   - owner.members
29   - end
30   -
31   - def extra_option
32   - data = {
33   - :human_name => _("Show join leave button"),
34   - :name => 'block[show_join_leave_button]',
35   - :value => true,
36   - :checked => show_join_leave_button,
37   - :options => {}
38   - }
39   - end
40   -
41   - def cache_key(language='en', user=nil)
42   - logged = ''
43   - if user
44   - logged += '-logged-in'
45   - if user.is_member_of? self.owner
46   - logged += '-member'
47   - end
48   - end
49   - super + logged
50   - end
51   -
52   -end
app/models/organization.rb
... ... @@ -123,7 +123,7 @@ class Organization &lt; Profile
123 123 [
124 124 [MainBlock.new],
125 125 [ProfileImageBlock.new, LinkListBlock.new(:links => links)],
126   - [MembersBlock.new, RecentDocumentsBlock.new]
  126 + [RecentDocumentsBlock.new]
127 127 ]
128 128 end
129 129  
... ...
app/models/people_block.rb
... ... @@ -1,25 +0,0 @@
1   -class PeopleBlock < ProfileListBlock
2   -
3   - def default_title
4   - _('People')
5   - end
6   -
7   - def help
8   - _('Clicking a person takes you to his/her homepage')
9   - end
10   -
11   - def self.description
12   - _('Random people')
13   - end
14   -
15   - def profiles
16   - owner.people
17   - end
18   -
19   - def footer
20   - lambda do |context|
21   - link_to _('View all'), :controller => 'search', :action => 'people'
22   - end
23   - end
24   -
25   -end
app/models/person.rb
... ... @@ -269,7 +269,7 @@ class Person &lt; Profile
269 269 [
270 270 [MainBlock.new],
271 271 [ProfileImageBlock.new(:show_name => true), LinkListBlock.new(:links => links), RecentDocumentsBlock.new],
272   - [FriendsBlock.new, CommunitiesBlock.new]
  272 + [CommunitiesBlock.new]
273 273 ]
274 274 end
275 275  
... ...
app/sweepers/friendship_sweeper.rb
... ... @@ -34,8 +34,7 @@ protected
34 34 expire_timeout_fragment(profile.manage_friends_cache_key(:npage => i.to_s))
35 35 end
36 36  
37   - blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)}
38   - BlockSweeper.expire_blocks(blocks)
  37 + expire_blocks_cache(profile, [:profile])
39 38 end
40 39  
41 40 end
... ...
app/views/blocks/members.html.erb
... ... @@ -1,5 +0,0 @@
1   -<%= link_to _('View all'), :profile => profile.identifier, :controller => 'profile', :action => 'members' %>
2   -
3   -<% if show_join_leave_button %>
4   - <%= render :partial => 'blocks/profile_info_actions/join_leave_community' %>
5   -<% end %>
app/views/layouts/application-ng.html.erb
... ... @@ -83,5 +83,10 @@
83 83 <%= noosfero_layout_features %>
84 84 <%= theme_javascript_ng %>
85 85 <%= addthis_javascript %>
  86 + <%=
  87 + @plugins.dispatch(:body_ending).map do |content|
  88 + if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end
  89 + end.join("\n")
  90 + %>
86 91 </body>
87 92 </html>
... ...
config/application.rb
... ... @@ -20,7 +20,7 @@ module Noosfero
20 20 require 'noosfero/plugin'
21 21  
22 22 # Adds custom attributes to the Set of allowed html attributes for the #sanitize helper
23   - config.action_view.sanitized_allowed_attributes = 'align', 'border', 'alt', 'vspace', 'hspace', 'width', 'heigth', 'value', 'type', 'data', 'style', 'target', 'codebase', 'archive', 'classid', 'code', 'flashvars', 'scrolling', 'frameborder', 'controls', 'autoplay'
  23 + config.action_view.sanitized_allowed_attributes = 'align', 'border', 'alt', 'vspace', 'hspace', 'width', 'heigth', 'value', 'type', 'data', 'style', 'target', 'codebase', 'archive', 'classid', 'code', 'flashvars', 'scrolling', 'frameborder', 'controls', 'autoplay', 'colspan', 'rowspan'
24 24  
25 25 # Adds custom tags to the Set of allowed html tags for the #sanitize helper
26 26 config.action_view.sanitized_allowed_tags = 'object', 'embed', 'param', 'table', 'tr', 'th', 'td', 'applet', 'comment', 'iframe', 'audio', 'video', 'source'
... ...
config/plugins/people_block 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../plugins/people_block
0 2 \ No newline at end of file
... ...
db/migrate/20140415125414_add_created_by_to_article.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class AddCreatedByToArticle < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :articles, :created_by_id, :integer
  4 + add_column :article_versions, :created_by_id, :integer
  5 +
  6 + execute("UPDATE article_versions SET created_by_id = last_changed_by_id")
  7 +
  8 + execute("UPDATE articles SET created_by_id = article_versions.created_by_id
  9 +FROM article_versions WHERE article_versions.article_id = articles.id AND
  10 +article_versions.version = 1")
  11 + end
  12 +
  13 + def self.down
  14 + remove_column :articles, :created_by_id
  15 + remove_column :article_versions, :created_by_id
  16 + end
  17 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20140408172149) do
  14 +ActiveRecord::Schema.define(:version => 20140415125414) do
15 15  
16 16 create_table "abuse_reports", :force => true do |t|
17 17 t.integer "reporter_id"
... ... @@ -95,6 +95,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140408172149) do
95 95 t.integer "license_id"
96 96 t.integer "image_id"
97 97 t.integer "position"
  98 + t.integer "created_by_id"
98 99 end
99 100  
100 101 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id"
... ... @@ -140,6 +141,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140408172149) do
140 141 t.integer "license_id"
141 142 t.integer "image_id"
142 143 t.integer "position"
  144 + t.integer "created_by_id"
143 145 end
144 146  
145 147 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
... ...
features/my_network_block.feature
... ... @@ -9,9 +9,11 @@ Feature: my_network_block
9 9 And the following blocks
10 10 | owner | type |
11 11 | joaosilva | MyNetworkBlock |
  12 + | joaosilva | FriendsBlock |
12 13 And the following communities
13 14 | identifier | name | public_profile |
14 15 | public-community | Public Community | true |
  16 + And plugin FriendsBlock is enabled on environment
15 17  
16 18 @selenium
17 19 Scenario: display how many public/private communities I am member
... ... @@ -46,6 +48,10 @@ Feature: my_network_block
46 48 | login | name | public_profile |
47 49 | mariasilva | Maria Silva | true |
48 50 | josesilva | Jose Silva | false |
  51 + And the following blocks
  52 + | owner | type |
  53 + | mariasilva | FriendsBlock |
  54 + | josesilva | FriendsBlock |
49 55 And "joaosilva" is friend of "mariasilva"
50 56 And I am logged in as "joaosilva"
51 57 And I am on joaosilva's homepage
... ... @@ -59,6 +65,10 @@ Feature: my_network_block
59 65 | login | name |
60 66 | mariasilva | Maria Silva |
61 67 | josesilva | Jose Silva |
  68 + And the following blocks
  69 + | owner | type |
  70 + | mariasilva | FriendsBlock |
  71 + | josesilva | FriendsBlock |
62 72 And "josesilva" is invisible
63 73 And "joaosilva" is friend of "mariasilva"
64 74 And I am logged in as "joaosilva"
... ...
lib/noosfero/plugin.rb
... ... @@ -277,6 +277,12 @@ class Noosfero::Plugin
277 277 nil
278 278 end
279 279  
  280 + # -> Adds content to the ending of the page
  281 + # returns = lambda block that creates html code or raw rhtml/html.erb
  282 + def body_ending
  283 + nil
  284 + end
  285 +
280 286 # -> Adds content to the ending of the page head
281 287 # returns = lambda block that creates html code or raw rhtml/html.erb
282 288 def head_ending
... ...
plugins/display_content/lib/display_content_block.rb
... ... @@ -102,7 +102,7 @@ class DisplayContentBlock &lt; Block
102 102 end
103 103  
104 104 def parent_nodes
105   - @parent_nodes ||= self.holder.articles.find(nodes).map { |article| get_parent(article) }.compact.flatten
  105 + @parent_nodes ||= self.holder.articles.where(:id => nodes).map { |article| get_parent(article) }.compact.flatten
106 106 end
107 107  
108 108 VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum']
... ...
plugins/display_content/test/unit/display_content_block_test.rb
... ... @@ -549,7 +549,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
549 549 a1 = fast_create(PluginArticle, :name => 'test article 1', :profile_id => profile.id)
550 550 Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
551 551 env = fast_create(Environment)
552   - env.enable_plugin(Plugin1)
  552 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([Plugin1.new])
553 553  
554 554 block = DisplayContentBlock.new
555 555 box = mock()
... ... @@ -632,4 +632,19 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
632 632 assert_equal [UploadedFile, Event, TinyMceArticle, TextileArticle, RawHTMLArticle, Folder, Blog, Forum, Gallery, RssFeed, SomePluginContent], block.available_content_types
633 633 end
634 634  
  635 + should 'do not fail if a selected article was removed' do
  636 + profile = create_user('testuser').person
  637 + Article.delete_all
  638 + f1 = fast_create(Folder, :name => 'test folder 1', :profile_id => profile.id)
  639 + a1 = fast_create(TextileArticle, :name => 'test article 1', :profile_id => profile.id, :parent_id => f1.id)
  640 +
  641 + checked_articles= {a1.id => true}
  642 +
  643 + block = DisplayContentBlock.new
  644 + block.stubs(:holder).returns(profile)
  645 + block.checked_nodes= checked_articles
  646 + a1.destroy
  647 + assert_equal [], block.parent_nodes
  648 + end
  649 +
635 650 end
... ...
plugins/people_block/before_disable.rb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +raise "\nPeopleBlockPlugin shouldn't be enabled/disabled by hand, Noosfero" +
  2 + "\ninstallation already comes with it enabled by default!\n"
... ...
plugins/people_block/controllers/people_block_plugin_profile_controller.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class PeopleBlockPluginProfileController < ProfileController
  2 +
  3 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  4 +
  5 + def members
  6 + if is_cache_expired?(profile.members_cache_key(params))
  7 + if(params[:role_key])
  8 + role = Role.find_by_key_and_environment_id(params[:role_key], profile.environment)
  9 + @members = profile.members.with_role(role.id).includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage])
  10 + @members_title = role.name
  11 + else
  12 + @members = profile.members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage])
  13 + @members_title = 'members'
  14 + end
  15 + end
  16 + render "profile/members"
  17 + end
  18 +
  19 +end
... ...
plugins/people_block/db/migrate/20140605222753_enable_people_block_plugin.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class EnablePeopleBlockPlugin < ActiveRecord::Migration
  2 + def up
  3 + Environment.all.each do |env|
  4 + env.enabled_plugins << 'PeopleBlockPlugin'
  5 + env.enabled_plugins.uniq!
  6 + env.save!
  7 + end
  8 + end
  9 +
  10 + def down
  11 + Environment.all.each do |env|
  12 + env.enabled_plugins.delete_if {|i| i== 'PeopleBlockPlugin'}
  13 + env.save!
  14 + end
  15 + end
  16 +end
... ...
plugins/people_block/lib/ext/person.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +require_dependency 'person'
  2 +
  3 +class Person
  4 +
  5 + scope :with_role, lambda { |role_id|
  6 + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ["role_assignments.role_id = #{role_id}"] }
  7 + }
  8 +
  9 +end
... ...
plugins/people_block/lib/friends_block.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class FriendsBlock < PeopleBlockBase
  2 +
  3 + def self.description
  4 + _('Friends')
  5 + end
  6 +
  7 + def help
  8 + _('Clicking a friend takes you to his/her homepage')
  9 + end
  10 +
  11 + def default_title
  12 + n_('{#} friend', '{#} friends', profile_count)
  13 + end
  14 +
  15 + def profiles
  16 + owner.friends
  17 + end
  18 +
  19 + def footer
  20 + profile = self.owner
  21 + proc do
  22 + render :file => 'blocks/friends', :locals => { :profile => profile }
  23 + end
  24 + end
  25 +
  26 + def self.expire_on
  27 + { :profile => [:profile] }
  28 + end
  29 +
  30 +end
... ...
plugins/people_block/lib/members_block.rb 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +class MembersBlock < PeopleBlockBase
  2 + settings_items :show_join_leave_button, :type => :boolean, :default => false
  3 + settings_items :visible_role, :type => :string, :default => nil
  4 + attr_accessible :show_join_leave_button, :visible_role
  5 +
  6 + def self.description
  7 + _('Members')
  8 + end
  9 +
  10 + def help
  11 + _('Clicking a member takes you to his/her homepage')
  12 + end
  13 +
  14 + def default_title
  15 + title = role ? role.name : n_('members')
  16 + _('{#} %s') % title
  17 + end
  18 +
  19 + def profiles
  20 + role ? owner.members.with_role(role.id) : owner.members
  21 + end
  22 +
  23 + def footer
  24 + profile = self.owner
  25 + role_key = visible_role
  26 + s = show_join_leave_button
  27 + proc do
  28 + render :file => 'blocks/members', :locals => { :profile => profile, :show_join_leave_button => s, :role_key => role_key}
  29 + end
  30 + end
  31 +
  32 + def role
  33 + visible_role && !visible_role.empty? ? Role.find_by_key_and_environment_id(visible_role, owner.environment) : nil
  34 + end
  35 +
  36 + def roles
  37 + Profile::Roles.organization_member_roles(owner.environment)
  38 + end
  39 +
  40 + def extra_option
  41 + data = {
  42 + :human_name => _("Show join leave button"),
  43 + :name => 'block[show_join_leave_button]',
  44 + :value => true,
  45 + :checked => show_join_leave_button,
  46 + :options => {}
  47 + }
  48 + end
  49 +
  50 +end
... ...
plugins/people_block/lib/people_block.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +class PeopleBlock < PeopleBlockBase
  2 +
  3 + def self.description
  4 + _('People')
  5 + end
  6 +
  7 + def help
  8 + _('Clicking a person takes you to his/her homepage')
  9 + end
  10 +
  11 + def default_title
  12 + _('{#} People')
  13 + end
  14 +
  15 + def profiles
  16 + owner.people
  17 + end
  18 +
  19 + def footer
  20 + proc do
  21 + render :file => 'blocks/people'
  22 + end
  23 + end
  24 +
  25 +end
... ...
plugins/people_block/lib/people_block_base.rb 0 → 100644
... ... @@ -0,0 +1,100 @@
  1 +class PeopleBlockBase < Block
  2 + settings_items :prioritize_profiles_with_image, :type => :boolean, :default => true
  3 + settings_items :limit, :type => :integer, :default => 6
  4 + settings_items :name, :type => String, :default => ""
  5 + settings_items :address, :type => String, :default => ""
  6 + attr_accessible :name, :address, :prioritize_profiles_with_image
  7 +
  8 + def self.description
  9 + _('Random people')
  10 + end
  11 +
  12 + def help
  13 + _('Clicking on the people or groups will take you to their home page.')
  14 + end
  15 +
  16 + def default_title
  17 + _('{#} People')
  18 + end
  19 +
  20 + def view_title
  21 + title.gsub('{#}', profile_count.to_s)
  22 + end
  23 +
  24 + def profiles
  25 + owner.profiles
  26 + end
  27 +
  28 + def profile_list
  29 + result = nil
  30 + visible_profiles = profiles.visible.includes([:image,:domains,:preferred_domain,:environment])
  31 + if !prioritize_profiles_with_image
  32 + result = visible_profiles.all(:limit => limit, :order => 'updated_at DESC').sort_by{ rand }
  33 + elsif visible_profiles.with_image.count >= limit
  34 + result = visible_profiles.with_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand }
  35 + else
  36 + result = visible_profiles.with_image.sort_by{ rand } + visible_profiles.without_image.all(:limit => limit * 5, :order => 'updated_at DESC').sort_by{ rand }
  37 + end
  38 + result.slice(0..limit-1)
  39 + end
  40 +
  41 + def profile_count
  42 + profiles.visible.count
  43 + end
  44 +
  45 + def content(args={})
  46 + profiles = self.profile_list
  47 + title = self.view_title
  48 +
  49 + if !self.name.blank? && !self.address.blank?
  50 + name = self.name
  51 + expanded_address = expand_address(self.address)
  52 + end
  53 +
  54 + proc do
  55 + count = 0
  56 + list = profiles.map {|item|
  57 + count += 1
  58 + send(:profile_image_link, item, :minor )
  59 + }.join("\n")
  60 + if list.empty?
  61 + list = content_tag 'div', _('None'), :class => 'common-profile-list-block-none'
  62 + else
  63 + if !name.blank? && !expanded_address.blank?
  64 + list << content_tag(
  65 + 'div',
  66 + content_tag(
  67 + 'li',
  68 + content_tag(
  69 + 'div',
  70 + link_to(
  71 + content_tag('span', name, :class => 'banner-span' ),
  72 + expanded_address,
  73 + :title => name
  74 + ),
  75 + :class => 'banner-div'
  76 + ),
  77 + :class => 'vcard'
  78 + ),
  79 + :class => 'common-profile-list-block'
  80 + )
  81 + end
  82 + list = content_tag 'ul', list
  83 + end
  84 + block_title(title) + content_tag('div', list + tag('br', :style => 'clear:both'))
  85 + end
  86 + end
  87 +
  88 + def expand_address(address)
  89 + if address !~ /^[a-z]+:\/\// && address !~ /^\//
  90 + 'http://' + address
  91 + else
  92 + address
  93 + end
  94 + end
  95 +
  96 + def extra_option
  97 + { }
  98 + end
  99 +
  100 +end
... ...
plugins/people_block/lib/people_block_plugin.rb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +class PeopleBlockPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "People Block Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("A plugin that adds a people block")
  9 + end
  10 +
  11 + def self.extra_blocks
  12 + {
  13 + PeopleBlock => {:type => Environment},
  14 + MembersBlock => {:type => Community},
  15 + FriendsBlock => {:type => Person}
  16 + }
  17 + end
  18 +
  19 + def self.has_admin_url?
  20 + false
  21 + end
  22 +
  23 + def stylesheet?
  24 + true
  25 + end
  26 +
  27 +end
... ...
plugins/people_block/public/style.css 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +/*******************************************************************
  2 + * COMMON *
  3 + *******************************************************************/
  4 +.people-block .block-footer-content a {
  5 + position: absolute;
  6 + top: 2px;
  7 + right: 0px;
  8 + font-size: 11px;
  9 + color: #000;
  10 + text-decoration: none;
  11 + padding-right: 15px;
  12 +}
  13 +
  14 +.people-block .banner-span {
  15 + color: #000;
  16 + font-size: 14pt;
  17 + font-weight: bold;
  18 + background-color: #EEE;
  19 +}
  20 +
  21 +
  22 +/*******************************************************************
  23 + * MAIN BOX - 1 *
  24 + *******************************************************************/
  25 +.box-1 .people-block .banner-div {
  26 + line-height: 112px;
  27 +}
  28 +
  29 +.box-1 .people-block .banner-span {
  30 + width: 204px;
  31 +}
  32 +
  33 +
  34 +/*******************************************************************
  35 + * LEFT/RIGHT BOXES *
  36 + *******************************************************************/
  37 +.box-2 .people-block .banner-div,
  38 +.box-3 .people-block .banner-div {
  39 + line-height: 78px;
  40 +}
  41 +
  42 +.box-2 .people-block .banner-div a,
  43 +.box-3 .people-block .banner-div a {
  44 + height: 78px;
  45 +}
  46 +
  47 +.box-2 .people-block .banner-span,
  48 +.box-3 .people-block .banner-span {
  49 + width: 116px;
  50 +}
  51 +
  52 +.box-2 .people-block ul,
  53 +.box-3 .people-block ul {
  54 + min-width: 196px;
  55 + width: 192px;
  56 + margin: 0px 0px 0px -3px;
  57 + padding: 0px;
  58 +}
  59 +
  60 +/*******************************************************************
  61 + * BLOCKs *
  62 + *******************************************************************/
  63 +#content .friends-block ul,
  64 +#content .members-block ul {
  65 + min-width: 196px;
  66 + width: 192px;
  67 + margin: 0px 0px 0px -3px;
  68 + padding: 0px;
  69 +}
  70 +#content .box-1 .people-block ul,
  71 +#content .box-1 .friends-block ul,
  72 +#content .box-1 .members-block ul {
  73 + width: auto;
  74 + display: block;
  75 +}
  76 +#content .people-block .block-footer-content a,
  77 +#content .friends-block .block-footer-content a,
  78 +#content .members-block .block-footer-content a {
  79 + position: absolute;
  80 + top: 2px;
  81 + right: 0px;
  82 + font-size: 11px;
  83 + color: #000;
  84 + text-decoration: none;
  85 + padding-right: 15px;
  86 +}
  87 +#content .members-block .block-footer-content .join-leave-button a {
  88 + position: relative;
  89 + background-color: #EEE;
  90 + border: 1px solid #CCC;
  91 + color: #555;
  92 + padding-right: inherit;
  93 +}
  94 +#content .members-block .block-footer-content .join-leave-button a:hover {
  95 + color: #FFF;
  96 + background-color: #555;
  97 + border: 1px solid #2e3436;
  98 + text-decoration: none;
  99 +}
  100 +#content .people-block .block-footer-content a.view-all,
  101 +#content .friends-block .block-footer-content a.view-all,
  102 +#content .members-block .block-footer-content a.view-all {
  103 + background: url(/designs/themes/base/imgs/arrow-right-p.png) 100% 50% no-repeat;
  104 +}
... ...
plugins/people_block/test/functional/people_block_plugin_environment_design_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class EnvironmentDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class EnvironmentDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = EnvironmentDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([PeopleBlockPlugin.new])
  13 + end
  14 +
  15 + should 'be able to edit PeopleBlock' do
  16 + login_as(create_admin_user(Environment.default))
  17 + b = PeopleBlock.create!
  18 + e = Environment.default
  19 + e.boxes.create!
  20 + e.boxes.first.blocks << b
  21 + get :edit, :id => b.id
  22 + assert_tag :tag => 'input', :attributes => { :id => 'block_limit' }
  23 + end
  24 +
  25 +end
... ...
plugins/people_block/test/functional/people_block_plugin_profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,76 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/people_block_plugin_profile_controller'
  3 +
  4 +
  5 +# Re-raise errors caught by the controller.
  6 +class PeopleBlockPluginProfileController; def rescue_action(e) raise e end; end
  7 +
  8 +class PeopleBlockPluginProfileControllerTest < ActionController::TestCase
  9 +
  10 + def setup
  11 + @controller = PeopleBlockPluginProfileController.new
  12 + @request = ActionController::TestRequest.new
  13 + @response = ActionController::TestResponse.new
  14 +
  15 + @profile = fast_create(Community)
  16 +
  17 + @environment = @profile.environment
  18 + @environment.enabled_plugins = ['PeopleBlockPlugin']
  19 + @environment.save!
  20 +
  21 + MembersBlock.delete_all
  22 + @block = MembersBlock.new
  23 + @block.box = @profile.boxes.first
  24 + @block.save!
  25 +
  26 + @admin = create_user('adminprofile').person
  27 + @member = create_user('memberprofile').person
  28 + @moderator = create_user('moderatorprofile').person
  29 + @profile.add_moderator(@moderator)
  30 + @profile.add_member(@member)
  31 + @profile.add_admin(@admin)
  32 + end
  33 +
  34 + attr_accessor :profile, :block, :admin, :member, :moderator
  35 +
  36 + should 'list members without role_key' do
  37 + get :members, :profile => profile.identifier
  38 + assert_response :success
  39 + assert_template 'members'
  40 + assert_equivalent [@admin, @member, @moderator], assigns(:members)
  41 + assert_match /adminprofile/, @response.body
  42 + assert_match /memberprofile/, @response.body
  43 + assert_match /moderatorprofile/, @response.body
  44 + end
  45 +
  46 + should 'list members with role_key=nil' do
  47 + get :members, :profile => profile.identifier, :role_key => nil
  48 + assert_response :success
  49 + assert_template 'members'
  50 + assert_equivalent [@admin, @member, @moderator], assigns(:members)
  51 + assert_match /adminprofile/, @response.body
  52 + assert_match /memberprofile/, @response.body
  53 + assert_match /moderatorprofile/, @response.body
  54 + end
  55 +
  56 + should 'list members only' do
  57 + get :members, :profile => profile.identifier, :role_key => Profile::Roles.member(profile.environment.id).key
  58 + assert_response :success
  59 + assert_template 'members'
  60 + assert_equal [@member], assigns(:members)
  61 + assert_no_match /adminprofile/, @response.body
  62 + assert_match /memberprofile/, @response.body
  63 + assert_no_match /moderatorprofile/, @response.body
  64 + end
  65 +
  66 + should 'list moderators only' do
  67 + get :members, :profile => profile.identifier, :role_key => Profile::Roles.moderator(profile.environment.id).key
  68 + assert_response :success
  69 + assert_template 'members'
  70 + assert_equal [@moderator], assigns(:members)
  71 + assert_no_match /adminprofile/, @response.body
  72 + assert_no_match /memberprofile/, @response.body
  73 + assert_match /moderatorprofile/, @response.body
  74 + end
  75 +
  76 +end
... ...
plugins/people_block/test/functional/people_block_plugin_profile_design_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,70 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class ProfileDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class ProfileDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = ProfileDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([PeopleBlockPlugin.new])
  13 + end
  14 +
  15 + should 'display *block people-block* class at design blocks page' do
  16 + user = create_user('testinguser')
  17 + login_as(user.login)
  18 +
  19 + @profile = user.person
  20 + @environment = @profile.environment
  21 + @environment.save!
  22 +
  23 + FriendsBlock.delete_all
  24 + @box1 = Box.create!(:owner => @profile)
  25 + @profile.boxes = [@box1]
  26 +
  27 + @block = FriendsBlock.new
  28 + @block.box = @box1
  29 + @block.save!
  30 +
  31 + @profile.blocks<<@block
  32 + @profile.save!
  33 +
  34 + get :index, :profile => @profile.identifier
  35 + assert_tag :div, :attributes => {:class => 'block friends-block'}
  36 + end
  37 +
  38 + should 'the people block is available for person profile' do
  39 + profile = mock
  40 + profile.stubs(:has_members?).returns(false)
  41 + profile.stubs(:person?).returns(true)
  42 + profile.stubs(:community?).returns(false)
  43 + profile.stubs(:enterprise?).returns(false)
  44 + profile.stubs(:has_blog?).returns(false)
  45 + profile.stubs(:is_admin?).with(anything).returns(false)
  46 + environment = mock
  47 + profile.stubs(:environment).returns(environment)
  48 + environment.stubs(:enabled?).returns(false)
  49 + @controller.stubs(:profile).returns(profile)
  50 + @controller.stubs(:user).returns(profile)
  51 + assert_includes @controller.available_blocks, FriendsBlock
  52 + end
  53 +
  54 + should 'the people block is available for community profile' do
  55 + profile = mock
  56 + profile.stubs(:has_members?).returns(true)
  57 + profile.stubs(:person?).returns(false)
  58 + profile.stubs(:community?).returns(true)
  59 + profile.stubs(:enterprise?).returns(false)
  60 + profile.stubs(:has_blog?).returns(false)
  61 + profile.stubs(:is_admin?).with(anything).returns(false)
  62 + environment = mock
  63 + profile.stubs(:environment).returns(environment)
  64 + environment.stubs(:enabled?).returns(false)
  65 + @controller.stubs(:profile).returns(profile)
  66 + @controller.stubs(:user).returns(profile)
  67 + assert_includes @controller.available_blocks, MembersBlock
  68 + end
  69 +
  70 +end
... ...
plugins/people_block/test/test_helper.rb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
... ...
plugins/people_block/test/unit/friends_block_test.rb 0 → 100644
... ... @@ -0,0 +1,156 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class FriendsBlockTest < ActiveSupport::TestCase
  4 +
  5 + should 'inherit from Block' do
  6 + assert_kind_of Block, FriendsBlock.new
  7 + end
  8 +
  9 +
  10 + should 'declare its default title' do
  11 + assert_not_equal Block.new.default_title, FriendsBlock.new.default_title
  12 + end
  13 +
  14 +
  15 + should 'describe itself' do
  16 + assert_not_equal Block.description, FriendsBlock.description
  17 + end
  18 +
  19 +
  20 + should 'is editable' do
  21 + block = FriendsBlock.new
  22 + assert block.editable?
  23 + end
  24 +
  25 +
  26 + should 'have field limit' do
  27 + block = FriendsBlock.new
  28 + assert_respond_to block, :limit
  29 + end
  30 +
  31 +
  32 + should 'default value of limit' do
  33 + block = FriendsBlock.new
  34 + assert_equal 6, block.limit
  35 + end
  36 +
  37 +
  38 + should 'have field name' do
  39 + block = FriendsBlock.new
  40 + assert_respond_to block, :name
  41 + end
  42 +
  43 +
  44 + should 'default value of name' do
  45 + block = FriendsBlock.new
  46 + assert_equal "", block.name
  47 + end
  48 +
  49 +
  50 + should 'have field address' do
  51 + block = FriendsBlock.new
  52 + assert_respond_to block, :address
  53 + end
  54 +
  55 +
  56 + should 'default value of address' do
  57 + block = FriendsBlock.new
  58 + assert_equal "", block.address
  59 + end
  60 +
  61 +
  62 + should 'prioritize profiles with image by default' do
  63 + assert FriendsBlock.new.prioritize_people_with_image
  64 + end
  65 +
  66 +
  67 + should 'accept a limit of people to be displayed' do
  68 + block = FriendsBlock.new
  69 + block.limit = 20
  70 + assert_equal 20, block.limit
  71 + end
  72 +
  73 +
  74 + should 'list friends from person' do
  75 + owner = fast_create(Person)
  76 + friend1 = fast_create(Person)
  77 + friend2 = fast_create(Person)
  78 + owner.add_friend(friend1)
  79 + owner.add_friend(friend2)
  80 +
  81 + block = FriendsBlock.new
  82 +
  83 + block.expects(:owner).returns(owner).at_least_once
  84 + expects(:profile_image_link).with(friend1, :minor).returns(friend1.name)
  85 + expects(:profile_image_link).with(friend2, :minor).returns(friend2.name)
  86 + expects(:block_title).with(anything).returns('')
  87 +
  88 + content = instance_eval(&block.content)
  89 +
  90 + assert_match(/#{friend1.name}/, content)
  91 + assert_match(/#{friend2.name}/, content)
  92 + end
  93 +
  94 +
  95 + should 'link to "all friends"' do
  96 + person1 = create_user('mytestperson').person
  97 +
  98 + block = FriendsBlock.new
  99 + block.expects(:owner).returns(person1).at_least_once
  100 +
  101 + expects(:_).with('View all').returns('View all')
  102 + expects(:link_to).with('View all', :profile => 'mytestperson', :controller => 'profile', :action => 'friends').returns('link-to-friends')
  103 +
  104 + assert_equal 'link-to-friends', instance_eval(&block.footer)
  105 + end
  106 +
  107 +
  108 + should 'count number of owner friends' do
  109 + owner = fast_create(Person)
  110 + friend1 = fast_create(Person)
  111 + friend2 = fast_create(Person)
  112 + friend3 = fast_create(Person)
  113 + owner.add_friend(friend1)
  114 + owner.add_friend(friend2)
  115 + owner.add_friend(friend3)
  116 +
  117 + block = FriendsBlock.new
  118 + block.expects(:owner).returns(owner).at_least_once
  119 +
  120 + assert_equal 3, block.profile_count
  121 + end
  122 +
  123 +
  124 + should 'count number of public and private friends' do
  125 + owner = fast_create(Person)
  126 + private_p = fast_create(Person, {:public_profile => false})
  127 + public_p = fast_create(Person, {:public_profile => true})
  128 +
  129 + owner.add_friend(private_p)
  130 + owner.add_friend(public_p)
  131 +
  132 + block = FriendsBlock.new
  133 + block.expects(:owner).returns(owner).at_least_once
  134 +
  135 + assert_equal 2, block.profile_count
  136 + end
  137 +
  138 +
  139 + should 'not count number of invisible friends' do
  140 + owner = fast_create(Person)
  141 + private_p = fast_create(Person, {:visible => false})
  142 + public_p = fast_create(Person, {:visible => true})
  143 +
  144 + owner.add_friend(private_p)
  145 + owner.add_friend(public_p)
  146 +
  147 + block = FriendsBlock.new
  148 + block.expects(:owner).returns(owner).at_least_once
  149 +
  150 + assert_equal 1, block.profile_count
  151 + end
  152 +
  153 + protected
  154 + include NoosferoTestHelper
  155 +
  156 +end
... ...
plugins/people_block/test/unit/members_block_test.rb 0 → 100644
... ... @@ -0,0 +1,252 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class MembersBlockTest < ActiveSupport::TestCase
  4 +
  5 + should 'inherit from Block' do
  6 + assert_kind_of Block, MembersBlock.new
  7 + end
  8 +
  9 +
  10 + should 'declare its default title' do
  11 + assert_not_equal Block.new.default_title, MembersBlock.new.default_title
  12 + end
  13 +
  14 +
  15 + should 'describe itself' do
  16 + assert_not_equal Block.description, MembersBlock.description
  17 + end
  18 +
  19 +
  20 + should 'is editable' do
  21 + block = MembersBlock.new
  22 + assert block.editable?
  23 + end
  24 +
  25 +
  26 + should 'have field limit' do
  27 + block = MembersBlock.new
  28 + assert_respond_to block, :limit
  29 + end
  30 +
  31 +
  32 + should 'default value of limit' do
  33 + block = MembersBlock.new
  34 + assert_equal 6, block.limit
  35 + end
  36 +
  37 +
  38 + should 'have field name' do
  39 + block = MembersBlock.new
  40 + assert_respond_to block, :name
  41 + end
  42 +
  43 +
  44 + should 'default value of name' do
  45 + block = MembersBlock.new
  46 + assert_equal "", block.name
  47 + end
  48 +
  49 +
  50 + should 'have field address' do
  51 + block = MembersBlock.new
  52 + assert_respond_to block, :address
  53 + end
  54 +
  55 +
  56 + should 'default value of address' do
  57 + block = MembersBlock.new
  58 + assert_equal "", block.address
  59 + end
  60 +
  61 +
  62 + should 'prioritize profiles with image by default' do
  63 + assert MembersBlock.new.prioritize_people_with_image
  64 + end
  65 +
  66 +
  67 + should 'respect limit when listing members' do
  68 + community = fast_create(Community)
  69 + p1 = fast_create(Person)
  70 + p2 = fast_create(Person)
  71 + p3 = fast_create(Person)
  72 + p4 = fast_create(Person)
  73 +
  74 + community.add_member(p1)
  75 + community.add_member(p2)
  76 + community.add_member(p3)
  77 + community.add_member(p4)
  78 +
  79 + block = MembersBlock.new(:limit => 3)
  80 + block.stubs(:owner).returns(community)
  81 +
  82 + assert_equal 3, block.profile_list.size
  83 + end
  84 +
  85 +
  86 + should 'accept a limit of members to be displayed' do
  87 + block = MembersBlock.new
  88 + block.limit = 20
  89 + assert_equal 20, block.limit
  90 + end
  91 +
  92 +
  93 + should 'list members from community' do
  94 + owner = fast_create(Community)
  95 + person1 = fast_create(Person)
  96 + person2 = fast_create(Person)
  97 + owner.add_member(person1)
  98 + owner.add_member(person2)
  99 +
  100 + block = MembersBlock.new
  101 +
  102 + block.expects(:owner).returns(owner).at_least_once
  103 + expects(:profile_image_link).with(person1, :minor).returns(person1.name)
  104 + expects(:profile_image_link).with(person2, :minor).returns(person2.name)
  105 + expects(:block_title).with(anything).returns('')
  106 +
  107 + content = instance_eval(&block.content)
  108 +
  109 + assert_match(/#{person1.name}/, content)
  110 + assert_match(/#{person2.name}/, content)
  111 + end
  112 +
  113 + should 'count number of public and private members' do
  114 + owner = fast_create(Community)
  115 + private_p = fast_create(Person, {:public_profile => false})
  116 + public_p = fast_create(Person, {:public_profile => true})
  117 +
  118 + owner.add_member(private_p)
  119 + owner.add_member(public_p)
  120 +
  121 + block = MembersBlock.new
  122 + block.expects(:owner).returns(owner).at_least_once
  123 +
  124 + assert_equal 2, block.profile_count
  125 + end
  126 +
  127 +
  128 + should 'not count number of invisible members' do
  129 + owner = fast_create(Community)
  130 + private_p = fast_create(Person, {:visible => false})
  131 + public_p = fast_create(Person, {:visible => true})
  132 +
  133 + owner.add_member(private_p)
  134 + owner.add_member(public_p)
  135 +
  136 + block = MembersBlock.new
  137 + block.expects(:owner).returns(owner).at_least_once
  138 +
  139 + assert_equal 1, block.profile_count
  140 + end
  141 +
  142 + should 'provide link to members page without a visible_role selected' do
  143 + profile = create_user('mytestuser').person
  144 + block = MembersBlock.new
  145 + block.box = profile.boxes.first
  146 + block.save!
  147 +
  148 + expects(:_).with('View all').returns('View all')
  149 + expects(:link_to).with('View all' , :profile => 'mytestuser', :controller => 'people_block_plugin_profile', :action => 'members', :role_key => block.visible_role).returns('link-to-members')
  150 +
  151 + assert_equal 'link-to-members', instance_eval(&block.footer)
  152 + end
  153 +
  154 + should 'provide link to members page with a selected role' do
  155 + profile = create_user('mytestuser').person
  156 + block = MembersBlock.new
  157 + block.box = profile.boxes.first
  158 + block.visible_role = 'profile_member'
  159 + block.save!
  160 +
  161 + expects(:_).with('View all').returns('View all')
  162 + expects(:link_to).with('View all' , :profile => 'mytestuser', :controller => 'people_block_plugin_profile', :action => 'members', :role_key => block.visible_role).returns('link-to-members')
  163 +
  164 + assert_equal 'link-to-members', instance_eval(&block.footer)
  165 + end
  166 +
  167 + should 'provide a role to be displayed (and default to nil)' do
  168 + env = fast_create(Environment)
  169 + env.boxes << Box.new
  170 + block = MembersBlock.new
  171 + assert_equal nil, block.visible_role
  172 + env.boxes.first.blocks << block
  173 + block.visible_role = 'profile_member'
  174 + block.save!
  175 + assert_equal 'profile_member', block.visible_role
  176 + end
  177 +
  178 + should 'list all members' do
  179 + env = fast_create(Environment)
  180 + env.boxes << Box.new
  181 + profile1 = fast_create(Person, :environment_id => env.id)
  182 + profile2 = fast_create(Person, :environment_id => env.id)
  183 +
  184 + block = MembersBlock.new
  185 + owner = fast_create(Community)
  186 + block.stubs(:owner).returns(owner)
  187 + env.boxes.first.blocks << block
  188 + block.save!
  189 +
  190 + owner.add_member profile1
  191 + owner.add_member profile2
  192 + profiles = block.profiles
  193 +
  194 + assert_includes profiles, profile1
  195 + assert_includes profiles, profile2
  196 + end
  197 +
  198 + should 'list only profiles with moderator role' do
  199 + env = fast_create(Environment)
  200 + env.boxes << Box.new
  201 + profile1 = fast_create(Person, :environment_id => env.id)
  202 + profile2 = fast_create(Person, :environment_id => env.id)
  203 +
  204 + block = MembersBlock.new
  205 + owner = fast_create(Community)
  206 + block.visible_role = Profile::Roles.moderator(owner.environment.id).key
  207 + block.stubs(:owner).returns(owner)
  208 + env.boxes.first.blocks << block
  209 + block.save!
  210 +
  211 + owner.add_member profile2
  212 + owner.add_moderator profile1
  213 + profiles = block.profiles
  214 +
  215 + assert_includes profiles, profile1
  216 + assert_not_includes profiles, profile2
  217 + end
  218 +
  219 + should 'list only profiles with member role' do
  220 + env = fast_create(Environment)
  221 + env.boxes << Box.new
  222 + profile1 = fast_create(Person, :environment_id => env.id)
  223 + profile2 = fast_create(Person, :environment_id => env.id)
  224 +
  225 + block = MembersBlock.new
  226 + owner = fast_create(Community)
  227 + block.visible_role = Profile::Roles.member(owner.environment.id).key
  228 + block.stubs(:owner).returns(owner)
  229 + env.boxes.first.blocks << block
  230 + block.save!
  231 +
  232 + owner.add_member profile2
  233 + owner.add_moderator profile1
  234 + profiles = block.profiles
  235 +
  236 + assert_not_includes profiles, profile1
  237 + assert_includes profiles, profile2
  238 + end
  239 +
  240 + should 'list available roles' do
  241 + block = MembersBlock.new
  242 + owner = fast_create(Community)
  243 + block.stubs(:owner).returns(owner)
  244 + assert_includes block.roles, Profile::Roles.member(owner.environment.id)
  245 + assert_includes block.roles, Profile::Roles.admin(owner.environment.id)
  246 + assert_includes block.roles, Profile::Roles.moderator(owner.environment.id)
  247 + end
  248 +
  249 + protected
  250 + include NoosferoTestHelper
  251 +
  252 +end
... ...
plugins/people_block/test/unit/people_block_plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class PeopleBlockPluginTest < ActiveSupport::TestCase
  4 +
  5 + should "return PeopleBlock in extra_blocks class method" do
  6 + assert PeopleBlockPlugin.extra_blocks.keys.include?(PeopleBlock)
  7 + end
  8 +
  9 + should "return MembersBlock in extra_blocks class method" do
  10 + assert PeopleBlockPlugin.extra_blocks.keys.include?(MembersBlock)
  11 + end
  12 +
  13 + should "return FriendsBlock in extra_blocks class method" do
  14 + assert PeopleBlockPlugin.extra_blocks.keys.include?(FriendsBlock)
  15 + end
  16 +
  17 + should "return false for class method has_admin_url?" do
  18 + assert !PeopleBlockPlugin.has_admin_url?
  19 + end
  20 +
  21 + should "return false for class method stylesheet?" do
  22 + assert PeopleBlockPlugin.new.stylesheet?
  23 + end
  24 +
  25 +end
... ...
plugins/people_block/test/unit/people_block_test.rb 0 → 100644
... ... @@ -0,0 +1,146 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class PeopleBlockTest < ActiveSupport::TestCase
  4 +
  5 + should 'inherit from Block' do
  6 + assert_kind_of Block, PeopleBlock.new
  7 + end
  8 +
  9 +
  10 + should 'declare its default title' do
  11 + assert_not_equal Block.new.default_title, PeopleBlock.new.default_title
  12 + end
  13 +
  14 +
  15 + should 'describe itself' do
  16 + assert_not_equal Block.description, PeopleBlock.description
  17 + end
  18 +
  19 +
  20 + should 'is editable' do
  21 + block = PeopleBlock.new
  22 + assert block.editable?
  23 + end
  24 +
  25 +
  26 + should 'have field limit' do
  27 + block = PeopleBlock.new
  28 + assert_respond_to block, :limit
  29 + end
  30 +
  31 +
  32 + should 'default value of limit' do
  33 + block = PeopleBlock.new
  34 + assert_equal 6, block.limit
  35 + end
  36 +
  37 +
  38 + should 'have field name' do
  39 + block = PeopleBlock.new
  40 + assert_respond_to block, :name
  41 + end
  42 +
  43 +
  44 + should 'default value of name' do
  45 + block = PeopleBlock.new
  46 + assert_equal "", block.name
  47 + end
  48 +
  49 +
  50 + should 'have field address' do
  51 + block = PeopleBlock.new
  52 + assert_respond_to block, :address
  53 + end
  54 +
  55 +
  56 + should 'default value of address' do
  57 + block = PeopleBlock.new
  58 + assert_equal "", block.address
  59 + end
  60 +
  61 +
  62 + should 'prioritize profiles with image by default' do
  63 + assert PeopleBlock.new.prioritize_profiles_with_image
  64 + end
  65 +
  66 +
  67 + should 'respect limit when listing people' do
  68 + env = fast_create(Environment)
  69 + p1 = fast_create(Person, :environment_id => env.id)
  70 + p2 = fast_create(Person, :environment_id => env.id)
  71 + p3 = fast_create(Person, :environment_id => env.id)
  72 + p4 = fast_create(Person, :environment_id => env.id)
  73 +
  74 + block = PeopleBlock.new(:limit => 3)
  75 + block.stubs(:owner).returns(env)
  76 +
  77 + assert_equal 3, block.profile_list.size
  78 + end
  79 +
  80 +
  81 + should 'accept a limit of people to be displayed' do
  82 + block = PeopleBlock.new
  83 + block.limit = 20
  84 + assert_equal 20, block.limit
  85 + end
  86 +
  87 +
  88 + should 'list people from environment' do
  89 + owner = fast_create(Environment)
  90 + person1 = fast_create(Person, :environment_id => owner.id)
  91 + person2 = fast_create(Person, :environment_id => owner.id)
  92 +
  93 + block = PeopleBlock.new
  94 +
  95 + block.expects(:owner).returns(owner).at_least_once
  96 + expects(:profile_image_link).with(person1, :minor).returns(person1.name)
  97 + expects(:profile_image_link).with(person2, :minor).returns(person2.name)
  98 + expects(:block_title).with(anything).returns('')
  99 +
  100 + content = instance_exec(&block.content)
  101 +
  102 + assert_match(/#{person1.name}/, content)
  103 + assert_match(/#{person2.name}/, content)
  104 + end
  105 +
  106 +
  107 + should 'link to "all people"' do
  108 + env = fast_create(Environment)
  109 +
  110 + block = PeopleBlock.new
  111 +
  112 + stubs(:_).with('View all').returns('View all')
  113 + stubs(:link_to).returns('link-to-people')
  114 + stubs(:url_for).returns(' ')
  115 +
  116 + assert_equal 'link-to-people', instance_exec(&block.footer)
  117 + end
  118 +
  119 +
  120 + should 'count number of public and private people' do
  121 + owner = fast_create(Environment)
  122 + private_p = fast_create(Person, :public_profile => false, :environment_id => owner.id)
  123 + public_p = fast_create(Person, :public_profile => true, :environment_id => owner.id)
  124 +
  125 + block = PeopleBlock.new
  126 + block.expects(:owner).returns(owner).at_least_once
  127 +
  128 + assert_equal 2, block.profile_count
  129 + end
  130 +
  131 +
  132 + should 'not count number of invisible people' do
  133 + owner = fast_create(Environment)
  134 + private_p = fast_create(Person, :visible => false, :environment_id => owner.id)
  135 + public_p = fast_create(Person, :visible => true, :environment_id => owner.id)
  136 +
  137 + block = PeopleBlock.new
  138 + block.expects(:owner).returns(owner).at_least_once
  139 +
  140 + assert_equal 1, block.profile_count
  141 + end
  142 +
  143 + protected
  144 + include NoosferoTestHelper
  145 +
  146 +end
... ...
plugins/people_block/views/blocks/friends.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= link_to s_('friends|View all'), {:profile => profile.identifier, :controller => 'profile', :action => 'friends'}, :class => 'view-all' %>
... ...
plugins/people_block/views/blocks/members.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<%= link_to _('View all'), {:profile => profile.identifier, :controller => 'people_block_plugin_profile', :action => 'members', :role_key => role_key}, :class => 'view-all' %>
  2 +
  3 +<% if show_join_leave_button %>
  4 + <%= render :partial => 'blocks/profile_info_actions/join_leave_community' %>
  5 +<% end %>
... ...
plugins/people_block/views/blocks/people.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= link_to _('View all'), {:controller => 'search', :action => 'people'}, :class => 'view-all' %>
... ...
plugins/people_block/views/box_organizer/_people_block_base.html.erb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<%= labelled_form_field _('Name:'), text_field(:block, :name) %>
  2 +
  3 +<%= labelled_form_field _('Address:'), text_field(:block, :address) %>
  4 +
  5 +<% if @block.kind_of?(MembersBlock) %>
  6 + <%= labelled_form_field _('Filter by role:'), '' %>
  7 + <%= select_tag 'block[visible_role]', options_for_select(@block.roles.map{|r| [r.name, r.key]}.insert(0,''), @block.visible_role) %>
  8 +<% end %>
  9 +
  10 +<%= render :partial => 'profile_list_block' %>
... ...
plugins/people_block/views/environment_design 0 → 120000
... ... @@ -0,0 +1 @@
  1 +box_organizer
0 2 \ No newline at end of file
... ...
plugins/people_block/views/profile_design 0 → 120000
... ... @@ -0,0 +1 @@
  1 +box_organizer
0 2 \ No newline at end of file
... ...
plugins/piwik/controllers/piwik_plugin_admin_controller.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class PiwikPluginAdminController < AdminController
  2 +
  3 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  4 +
  5 + def index
  6 + if request.post?
  7 + if @environment.update_attributes(params[:environment])
  8 + session[:notice] = _('Piwik plugin settings updated successfully.')
  9 + else
  10 + session[:notice] = _('Piwik plugin settings could not be saved.')
  11 + end
  12 + redirect_to :controller => 'plugins', :action => 'index'
  13 + end
  14 + end
  15 +
  16 +end
... ...
plugins/piwik/lib/ext/environment.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +require_dependency 'environment'
  2 +
  3 +class Environment
  4 + settings_items :piwik_domain
  5 + settings_items :piwik_site_id
  6 + attr_accessible :piwik_domain, :piwik_site_id
  7 +end
... ...
plugins/piwik/lib/piwik_plugin.rb 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +class PiwikPlugin < Noosfero::Plugin
  2 +
  3 + include ActionView::Helpers::JavaScriptHelper
  4 + include ActionView::Helpers::FormHelper
  5 + include ActionView::Helpers::UrlHelper
  6 + include ActionView::Helpers::TagHelper
  7 +
  8 + def self.plugin_name
  9 + "Piwik"
  10 + end
  11 +
  12 + def self.plugin_description
  13 + _("Tracking and web analytics to your Noosfero's environment")
  14 + end
  15 +
  16 + def body_ending
  17 + domain = context.environment.piwik_domain
  18 + site_id = context.environment.piwik_site_id
  19 + unless domain.blank? || site_id.blank?
  20 + expanded_template('tracking-code.rhtml',{:domain => domain, :site_id => site_id})
  21 + end
  22 + end
  23 +
  24 +end
... ...
plugins/piwik/test/functional/piwik_plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/piwik_plugin_admin_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class PiwikPluginAdminController; def rescue_action(e) raise e end; end
  6 +
  7 +class PiwikPluginAdminControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @environment = Environment.default
  11 + user_login = create_admin_user(@environment)
  12 + login_as(user_login)
  13 + @environment.enabled_plugins = ['PiwikPlugin']
  14 + @environment.save!
  15 + end
  16 +
  17 + should 'access index action' do
  18 + get :index
  19 + assert_template 'index'
  20 + assert_response :success
  21 + end
  22 +
  23 + should 'update piwik plugin settings' do
  24 + assert_nil @environment.reload.piwik_domain
  25 + assert_nil @environment.reload.piwik_site_id
  26 + post :index, :environment => { :piwik_domain => 'http://something', :piwik_site_id => 10 }
  27 + assert_not_nil @environment.reload.piwik_domain
  28 + assert_not_nil @environment.reload.piwik_site_id
  29 + end
  30 +
  31 +end
... ...
plugins/piwik/test/unit/piwik_plugin_test.rb 0 → 100644
... ... @@ -0,0 +1,42 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class PiwikPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = PiwikPlugin.new
  7 + @context = mock()
  8 + @plugin.context = @context
  9 + @environment = Environment.new
  10 + @context.stubs(:environment).returns(@environment)
  11 + end
  12 +
  13 + should 'add content at the body ending unless domain and site_id are blank' do
  14 + @environment.piwik_domain = 'piwik.domain.example.com'
  15 + @environment.piwik_site_id = 5
  16 + @plugin.stubs(:expanded_template).returns('content')
  17 + assert_equal 'content', @plugin.body_ending
  18 + end
  19 +
  20 + should 'not add any content at the body ending if domain is blank' do
  21 + @environment.piwik_domain = nil
  22 + @environment.piwik_site_id = 5
  23 + @plugin.stubs(:expanded_template).returns('content')
  24 + assert_equal nil, @plugin.body_ending
  25 + end
  26 +
  27 + should 'not add any content at the body ending if site_id is blank' do
  28 + @environment.piwik_domain = 'piwik.domain.example.com'
  29 + @environment.piwik_site_id = nil
  30 + @plugin.stubs(:expanded_template).returns('content')
  31 + assert_equal nil, @plugin.body_ending
  32 + end
  33 +
  34 + should 'extends Environment with attr piwik_domain' do
  35 + assert_respond_to Environment.new, :piwik_domain
  36 + end
  37 +
  38 + should 'extends Environment with attr piwik_site_id' do
  39 + assert_respond_to Environment.new, :piwik_site_id
  40 + end
  41 +
  42 +end
... ...
plugins/piwik/views/piwik_plugin_admin/index.html.erb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +<h1><%= _("Piwik plugin settings") %></h1>
  2 +
  3 +<%= form_for(:environment) do |f| %>
  4 +
  5 + <%= labelled_form_field _('Piwik domain'), f.text_field(:piwik_domain) %>
  6 +
  7 + <%= labelled_form_field _('Piwik site id'), f.text_field(:piwik_site_id) %>
  8 +
  9 + <% button_bar do %>
  10 + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %>
  11 + <% end %>
  12 +
  13 +<% end %>
... ...
plugins/piwik/views/tracking-code.rhtml 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +<!-- Piwik -->
  2 +<script type="text/javascript">
  3 + var _paq = _paq || [];
  4 + _paq.push(['trackPageView']);
  5 + _paq.push(['enableLinkTracking']);
  6 + (function() {
  7 + var u=(("https:" == document.location.protocol) ? "https" : "http") + "://<%= escape_javascript locals[:domain] %>/piwik/";
  8 + _paq.push(['setTrackerUrl', u+'piwik.php']);
  9 + _paq.push(['setSiteId', <%= escape_javascript locals[:site_id] %>]);
  10 + var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript';
  11 + g.defer=true; g.async=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
  12 + })();
  13 +</script>
  14 +<noscript><p><img src="http://<%= escape_javascript locals[:domain] %>/piwik/piwik.php?idsite=<%= escape_javascript locals[:site_id] %>" style="border:0;" alt="" /></p></noscript>
  15 +<!-- End Piwik Code -->
... ...
plugins/video/lib/video_block.rb
... ... @@ -6,8 +6,10 @@ class VideoBlock &lt; Block
6 6 settings_items :width, :type => :integer, :default => 400
7 7 settings_items :height, :type => :integer, :default => 315
8 8  
  9 + YOUTUBE_ID_FORMAT = '\w-'
  10 +
9 11 def is_youtube?
10   - url.match(/.*(youtube.com.*v=[[:alnum:]]+|youtu.be\/[[:alnum:]]+).*/) ? true : false
  12 + url.match(/.*(youtube.com.*v=[#{YOUTUBE_ID_FORMAT}]+|youtu.be\/[#{YOUTUBE_ID_FORMAT}]+).*/) ? true : false
11 13 end
12 14  
13 15 def is_vimeo?
... ... @@ -46,8 +48,8 @@ class VideoBlock &lt; Block
46 48  
47 49 def extract_youtube_id
48 50 return nil unless is_youtube?
49   - youtube_match = url.match('v=([[:alnum:]]*)')
50   - youtube_match ||= url.match('youtu.be\/([[:alnum:]]*)')
  51 + youtube_match = url.match("v=([#{YOUTUBE_ID_FORMAT}]*)")
  52 + youtube_match ||= url.match("youtu.be\/([#{YOUTUBE_ID_FORMAT}]*)")
51 53 youtube_match[1] unless youtube_match.nil?
52 54 end
53 55  
... ...
plugins/video/test/unit/video_block_test.rb
... ... @@ -70,6 +70,13 @@ class VideoBlockTest &lt; ActiveSupport::TestCase
70 70 assert_equal id, block.send('extract_youtube_id')
71 71 end
72 72  
  73 + should "extract youtube id from youtube video url's if it has underline and hyphen" do
  74 + block = VideoBlock.new
  75 + id = 'oi43_re-d2'
  76 + block.url = "youtube.com/?v=#{id}"
  77 + assert_equal id, block.send('extract_youtube_id')
  78 + end
  79 +
73 80 should "extract youtube id from youtube video url's if it's a valid youtube short url" do
74 81 block = VideoBlock.new
75 82 id = 'oi43jre2d2'
... ...
public/designs/themes/base/style.css
... ... @@ -478,12 +478,9 @@ div#notice {
478 478  
479 479 /************************** Profile List *****************************/
480 480  
481   -#content .people-block ul,
482 481 #content .profile-list-block ul,
483 482 #content .enterprises-block ul,
484   -#content .members-block ul,
485 483 #content .communities-block ul,
486   -#content .friends-block ul,
487 484 #content .fans-block ul {
488 485 min-width: 196px;
489 486 width: 192px;
... ... @@ -491,24 +488,18 @@ div#notice {
491 488 padding: 0px;
492 489 }
493 490  
494   -#content .box-1 .people-block ul,
495 491 #content .box-1 .profile-list-block ul,
496 492 #content .box-1 .enterprises-block ul,
497   -#content .box-1 .members-block ul,
498 493 #content .box-1 .communities-block ul,
499   -#content .box-1 .friends-block ul,
500 494 #content .box-1 .fans-block ul {
501 495 width: auto;
502 496 display: block;
503 497 }
504 498  
505 499 #content .tags-block .block-footer-content a,
506   -#content .people-block .block-footer-content a,
507 500 #content .profile-list-block .block-footer-content a,
508 501 #content .enterprises-block .block-footer-content a,
509   -#content .members-block .block-footer-content a,
510   -#content .communities-block .block-footer-content a,
511   -#content .friends-block .block-footer-content a {
  502 +#content .communities-block .block-footer-content a {
512 503 position: absolute;
513 504 top: 2px;
514 505 right: 0px;
... ... @@ -518,29 +509,12 @@ div#notice {
518 509 padding-right: 15px;
519 510 }
520 511 #content .tags-block .block-footer-content a,
521   -#content .people-block .block-footer-content a,
522 512 #content .profile-list-block .block-footer-content a,
523 513 #content .enterprises-block .block-footer-content a,
524   -#content .communities-block .block-footer-content a,
525   -#content .friends-block .block-footer-content a {
  514 +#content .communities-block .block-footer-content a {
526 515 background: url(imgs/arrow-right-p.png) 100% 50% no-repeat;
527 516 }
528 517  
529   -#content .members-block .block-footer-content .join-leave-button a {
530   - position: relative;
531   - background-color: #EEE;
532   - border: 1px solid #CCC;
533   - color: #555;
534   - padding-right: inherit;
535   -}
536   -
537   -#content .members-block .block-footer-content .join-leave-button a:hover {
538   - color: #FFF;
539   - background-color: #555;
540   - border: 1px solid #2e3436;
541   - text-decoration: none;
542   -}
543   -
544 518 #content .profile-list-block .block-title {
545 519 text-align: left;
546 520 }
... ...
public/plugins/people_block 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../plugins/people_block/public
0 2 \ No newline at end of file
... ...
script/noosfero-plugins
... ... @@ -76,7 +76,8 @@ run(){
76 76  
77 77 _enable(){
78 78 plugin="$1"
79   - source="$available_plugins_dir/$plugin"
  79 + cd $enabled_plugins_dir
  80 + source="../../plugins/$plugin"
80 81 target="$enabled_plugins_dir/$plugin"
81 82 run "$source/before_enable.rb"
82 83 if [ -h "$target" ]; then
... ... @@ -98,11 +99,13 @@ _enable(){
98 99 fi
99 100 fi
100 101 if [ "$installation_ok" = true ] && [ "$dependencies_ok" = true ]; then
101   - ln -s "$source" "$target"
  102 + ln -s "$source" "$plugin"
102 103 plugins_public_dir="$NOOSFERO_DIR/public/plugins"
103 104 plugins_features_dir="$NOOSFERO_DIR/features/plugins"
104   - test -d "$target/public/" && ln -s "$target/public" "$plugins_public_dir/$plugin"
105   - test -d "$NOOSFERO_DIR/features" && test -d "$target/features" && ln -s "$target/features" "$plugins_features_dir/$plugin"
  105 + cd $plugins_public_dir
  106 + test -d "$source/public" && ln -s "$source/public" "$plugin"
  107 + cd $plugins_features_dir
  108 + test -d "$NOOSFERO_DIR/features" && test -d "$source/features" && ln -s "$source/features" "$plugin"
106 109 _say "$plugin enabled"
107 110 run "$source/after_enable.rb"
108 111 needs_migrate=true
... ... @@ -122,15 +125,19 @@ _disable(){
122 125 target="$enabled_plugins_dir/$plugin"
123 126 plugins_public_dir="$NOOSFERO_DIR/public/plugins"
124 127 plugins_features_dir="$NOOSFERO_DIR/features/plugins"
125   - run "$source/before_disable.rb"
126   - if [ -h "$target" ]; then
127   - rm "$target"
128   - test -h "$plugins_public_dir/$plugin" && rm "$plugins_public_dir/$plugin"
129   - test -h "$plugins_features_dir/$plugin" && rm "$plugins_features_dir/$plugin"
130   - _say "$plugin disabled"
131   - run "$source/after_disable.rb"
  128 + if ! run "$source/before_disable.rb"; then
  129 + echo "W: failed to disabling $plugin"
  130 + echo
132 131 else
133   - _say "$plugin already disabled"
  132 + if [ -h "$target" ]; then
  133 + rm "$target"
  134 + test -h "$plugins_public_dir/$plugin" && rm "$plugins_public_dir/$plugin"
  135 + test -h "$plugins_features_dir/$plugin" && rm "$plugins_features_dir/$plugin"
  136 + _say "$plugin disabled"
  137 + run "$source/after_disable.rb"
  138 + else
  139 + _say "$plugin already disabled"
  140 + fi
134 141 fi
135 142 }
136 143  
... ...
test/functional/cms_controller_test.rb
... ... @@ -1228,7 +1228,7 @@ class CmsControllerTest &lt; ActionController::TestCase
1228 1228 should 'allow user edit article if he is owner and has publish permission' do
1229 1229 c = Community.create!(:name => 'test_comm', :identifier => 'test_comm')
1230 1230 u = create_user_with_permission('test_user', 'publish_content', c)
1231   - a = create(Article, :profile => c, :name => 'test_article', :last_changed_by => u)
  1231 + a = create(Article, :profile => c, :name => 'test_article', :created_by => u)
1232 1232 login_as :test_user
1233 1233 @controller.stubs(:user).returns(u)
1234 1234  
... ... @@ -1774,6 +1774,31 @@ class CmsControllerTest &lt; ActionController::TestCase
1774 1774 assert_equal 'first version', Article.find(article.id).name
1775 1775 end
1776 1776  
  1777 + should 'set created_by when creating article' do
  1778 + login_as(profile.identifier)
  1779 +
  1780 + post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :article => { :name => 'changed by me', :body => 'content ...' }
  1781 +
  1782 + a = profile.articles.find_by_path('changed-by-me')
  1783 + assert_not_nil a
  1784 + assert_equal profile, a.created_by
  1785 + end
  1786 +
  1787 + should 'not change created_by when updating article' do
  1788 + other_person = create_user('otherperson').person
  1789 +
  1790 + a = profile.articles.build(:name => 'my article')
  1791 + a.created_by = other_person
  1792 + a.save!
  1793 +
  1794 + login_as(profile.identifier)
  1795 + post :edit, :profile => profile.identifier, :id => a.id, :article => { :body => 'new content for this article' }
  1796 +
  1797 + a.reload
  1798 +
  1799 + assert_equal other_person, a.created_by
  1800 + end
  1801 +
1777 1802 protected
1778 1803  
1779 1804 # FIXME this is to avoid adding an extra dependency for a proper JSON parser.
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -743,7 +743,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
743 743 c = Community.create!(:name => 'test_com')
744 744 u = create_user_with_permission('test_user', 'publish_content', c)
745 745 login_as u.identifier
746   - a = create(Article, :profile => c, :name => 'test-article', :last_changed_by => u, :published => false)
  746 + a = create(Article, :profile => c, :name => 'test-article', :created_by => u, :published => false)
747 747  
748 748 get :view_page, :profile => c.identifier, :page => a.path
749 749  
... ...
test/functional/environment_design_controller_test.rb
... ... @@ -8,7 +8,7 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
8 8  
9 9 # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
10 10 # the Noosfero core soon, see ActionItem3045
11   - ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
  11 + ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
12 12  
13 13 def setup
14 14 @controller = EnvironmentDesignController.new
... ... @@ -107,16 +107,6 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
107 107 assert_tag :tag => 'input', :attributes => { :id => 'block_limit' }
108 108 end
109 109  
110   - should 'be able to edit PeopleBlock' do
111   - login_as(create_admin_user(Environment.default))
112   - b = PeopleBlock.create!
113   - e = Environment.default
114   - e.boxes.create!
115   - e.boxes.first.blocks << b
116   - get :edit, :id => b.id
117   - assert_tag :tag => 'input', :attributes => { :id => 'block_limit' }
118   - end
119   -
120 110 should 'be able to edit SlideshowBlock' do
121 111 login_as(create_admin_user(Environment.default))
122 112 b = SlideshowBlock.create!
... ...
test/functional/profile_design_controller_test.rb
... ... @@ -6,8 +6,7 @@ class ProfileDesignController; def rescue_action(e) raise e end; end
6 6 class ProfileDesignControllerTest < ActionController::TestCase
7 7  
8 8 COMMOM_BLOCKS = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9   - PERSON_BLOCKS = COMMOM_BLOCKS + [FriendsBlock, FavoriteEnterprisesBlock, CommunitiesBlock, EnterprisesBlock ]
10   - PERSON_BLOCKS_WITH_MEMBERS = PERSON_BLOCKS + [MembersBlock]
  9 + PERSON_BLOCKS = COMMOM_BLOCKS + [ FavoriteEnterprisesBlock, CommunitiesBlock, EnterprisesBlock ]
11 10 PERSON_BLOCKS_WITH_BLOG = PERSON_BLOCKS + [BlogArchivesBlock]
12 11  
13 12 ENTERPRISE_BLOCKS = COMMOM_BLOCKS + [DisabledEnterpriseMessageBlock, FeaturedProductsBlock, FansBlock, ProductCategoriesBlock]
... ... @@ -525,23 +524,6 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
525 524 assert_equal PERSON_BLOCKS, @controller.available_blocks
526 525 end
527 526  
528   - should 'the person with members blocks are all available' do
529   - profile = mock
530   - profile.stubs(:has_members?).returns(true)
531   - profile.stubs(:person?).returns(true)
532   - profile.stubs(:community?).returns(true)
533   - profile.stubs(:enterprise?).returns(false)
534   - profile.stubs(:has_blog?).returns(false)
535   - profile.stubs(:is_admin?).with(anything).returns(false)
536   - environment = mock
537   - profile.stubs(:environment).returns(environment)
538   - environment.stubs(:enabled?).returns(false)
539   - @controller.stubs(:profile).returns(profile)
540   - @controller.stubs(:user).returns(profile)
541   - Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([])
542   - assert_equal [], @controller.available_blocks - PERSON_BLOCKS_WITH_MEMBERS
543   - end
544   -
545 527 should 'the person with blog blocks are all available' do
546 528 profile = mock
547 529 profile.stubs(:has_members?).returns(false)
... ...
test/unit/article_test.rb
... ... @@ -154,7 +154,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
154 154 assert a4.errors[:slug.to_s].present?
155 155 end
156 156  
157   - should 'record who did the last change' do
  157 + should 'last_changed_by be a person' do
158 158 a = profile.articles.build(:name => 'test')
159 159  
160 160 # must be a person
... ... @@ -167,6 +167,19 @@ class ArticleTest &lt; ActiveSupport::TestCase
167 167 end
168 168 end
169 169  
  170 + should 'created_by be a person' do
  171 + a = profile.articles.build(:name => 'test')
  172 +
  173 + # must be a person
  174 + assert_raise ActiveRecord::AssociationTypeMismatch do
  175 + a.created_by = Profile.new
  176 + end
  177 + assert_nothing_raised do
  178 + a.created_by = Person.new
  179 + a.save!
  180 + end
  181 + end
  182 +
170 183 should 'not show private documents as recent' do
171 184 p = create_user('usr1').person
172 185 Article.destroy_all
... ... @@ -802,7 +815,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
802 815 should 'allow author to edit if is publisher' do
803 816 c = fast_create(Community)
804 817 p = create_user_with_permission('test_user', 'publish_content', c)
805   - a = create(Article, :name => 'a test article', :last_changed_by => p, :profile_id => c.id)
  818 + a = create(Article, :name => 'a test article', :created_by => p, :profile_id => c.id)
806 819  
807 820 assert a.allow_post_content?(p)
808 821 end
... ... @@ -1380,17 +1393,17 @@ class ArticleTest &lt; ActiveSupport::TestCase
1380 1393  
1381 1394 should "the author_name returns the name of the article's author" do
1382 1395 author = fast_create(Person)
1383   - a = create(Article, :name => 'a test article', :last_changed_by => author, :profile_id => profile.id)
  1396 + a = create(Article, :name => 'a test article', :created_by => author, :profile_id => profile.id)
1384 1397 assert_equal author.name, a.author_name
1385 1398 author.destroy
1386   - a.reload
  1399 + a = Article.find(a.id)
1387 1400 a.author_name = 'some name'
1388 1401 assert_equal 'some name', a.author_name
1389 1402 end
1390 1403  
1391 1404 should 'retrieve latest info from topic when has no comments' do
1392 1405 forum = fast_create(Forum, :name => 'Forum test', :profile_id => profile.id)
1393   - post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now, :last_changed_by_id => profile.id)
  1406 + post = fast_create(TextileArticle, :name => 'First post', :profile_id => profile.id, :parent_id => forum.id, :updated_at => Time.now, :last_changed_by_id => profile.id, :created_by_id => profile.id)
1394 1407 assert_equal post.updated_at, post.info_from_last_update[:date]
1395 1408 assert_equal profile.name, post.info_from_last_update[:author_name]
1396 1409 assert_equal profile.url, post.info_from_last_update[:author_url]
... ... @@ -1744,30 +1757,30 @@ class ArticleTest &lt; ActiveSupport::TestCase
1744 1757  
1745 1758 should 'set author_name before creating article if there is an author' do
1746 1759 author = fast_create(Person)
1747   - article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => author)
  1760 + article = create(Article, :name => 'Test', :profile => profile, :created_by => author)
1748 1761 assert_equal author.name, article.author_name
1749 1762  
1750 1763 author_name = author.name
1751 1764 author.destroy
1752   - article.reload
  1765 + article = Article.find(article.id)
1753 1766 assert_equal author_name, article.author_name
1754 1767 end
1755 1768  
1756 1769 should "author_id return the author id of the article's author" do
1757 1770 author = fast_create(Person)
1758   - article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => author)
  1771 + article = create(Article, :name => 'Test', :profile => profile, :created_by => author)
1759 1772 assert_equal author.id, article.author_id
1760 1773 end
1761 1774  
1762 1775 should "author_id return nil if there is no article's author" do
1763   - article = create(Article, :name => 'Test', :profile => profile, :last_changed_by => nil)
  1776 + article = create(Article, :name => 'Test', :profile => profile, :created_by => nil)
1764 1777 assert_nil article.author_id
1765 1778 end
1766 1779  
1767 1780 should "return the author of a specific version" do
1768 1781 author1 = fast_create(Person)
1769 1782 author2 = fast_create(Person)
1770   - article = create(Article, :name => 'first version', :profile => profile, :last_changed_by => author1)
  1783 + article = create(Article, :name => 'first version', :profile => profile, :created_by => author1, :last_changed_by => author1)
1771 1784 article.name = 'second version'
1772 1785 article.last_changed_by = author2
1773 1786 article.save
... ... @@ -1778,7 +1791,7 @@ class ArticleTest &lt; ActiveSupport::TestCase
1778 1791 should "return the author_name of a specific version" do
1779 1792 author1 = fast_create(Person)
1780 1793 author2 = fast_create(Person)
1781   - article = create(Article, :name => 'first version', :profile => profile, :last_changed_by => author1)
  1794 + article = create(Article, :name => 'first version', :profile => profile, :created_by => author1)
1782 1795 article.name = 'second version'
1783 1796 article.last_changed_by = author2
1784 1797 article.save
... ... @@ -1828,4 +1841,12 @@ class ArticleTest &lt; ActiveSupport::TestCase
1828 1841 assert_equivalent [c3], Article.with_types(['Event'])
1829 1842 end
1830 1843  
  1844 + should 'not create version when receive a comment' do
  1845 + a = Article.new(:name => 'my article', :body => 'my text')
  1846 + a.profile = profile
  1847 + a.save!
  1848 + Comment.create!(:title => 'test', :body => 'asdsad', :author => profile, :source => a)
  1849 + assert_equal 1, a.versions.count
  1850 + end
  1851 +
1831 1852 end
... ...
test/unit/box_test.rb
... ... @@ -39,14 +39,11 @@ class BoxTest &lt; ActiveSupport::TestCase
39 39 assert blocks.include?('fans-block')
40 40 assert blocks.include?('favorite-enterprises-block')
41 41 assert blocks.include?('feed-reader-block')
42   - assert blocks.include?('friends-block')
43 42 assert blocks.include?('highlights-block')
44 43 assert blocks.include?('link-list-block')
45 44 assert blocks.include?('login-block')
46 45 assert blocks.include?('main-block')
47   - assert blocks.include?('members-block')
48 46 assert blocks.include?('my-network-block')
49   - assert blocks.include?('people-block')
50 47 assert blocks.include?('profile-image-block')
51 48 assert blocks.include?('raw-html-block')
52 49 assert blocks.include?('recent-documents-block')
... ... @@ -74,14 +71,11 @@ class BoxTest &lt; ActiveSupport::TestCase
74 71 assert blocks.include?('favorite-enterprises-block')
75 72 assert blocks.include?('featured-products-block')
76 73 assert blocks.include?('feed-reader-block')
77   - assert blocks.include?('friends-block')
78 74 assert blocks.include?('highlights-block')
79 75 assert blocks.include?('link-list-block')
80 76 assert blocks.include?('location-block')
81 77 assert blocks.include?('login-block')
82   - assert blocks.include?('members-block')
83 78 assert blocks.include?('my-network-block')
84   - assert blocks.include?('people-block')
85 79 assert blocks.include?('products-block')
86 80 assert blocks.include?('profile-image-block')
87 81 assert blocks.include?('profile-info-block')
... ...
test/unit/forum_helper_test.rb
... ... @@ -38,7 +38,7 @@ class ForumHelperTest &lt; ActiveSupport::TestCase
38 38  
39 39 should 'return post update if it has no comments' do
40 40 author = create_user('forum test author').person
41   - some_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => forum, :published => true, :last_changed_by => author)
  41 + some_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => forum, :published => true, :created_by => author)
42 42 assert some_post.comments.empty?
43 43 out = last_topic_update(some_post)
44 44 assert_match some_post.updated_at.to_s, out
... ...
test/unit/friends_block_test.rb
... ... @@ -1,86 +0,0 @@
1   -require File.dirname(__FILE__) + '/../test_helper'
2   -
3   -class FriendsBlockTest < ActiveSupport::TestCase
4   -
5   - should 'describe itself' do
6   - assert_not_equal ProfileListBlock.description, FriendsBlock.description
7   - end
8   -
9   - should 'declare its default title' do
10   - FriendsBlock.any_instance.stubs(:profile_count).returns(0)
11   - assert_not_equal ProfileListBlock.new.default_title, FriendsBlock.new.default_title
12   - end
13   -
14   - should 'list owner friends' do
15   - p1 = create_user('testuser1').person
16   - p2 = create_user('testuser2').person
17   - p3 = create_user('testuser3').person
18   - p4 = create_user('testuser4').person
19   -
20   - p1.add_friend(p2)
21   - p1.add_friend(p3)
22   - p1.add_friend(p4)
23   - p1.friends.reload
24   -
25   - block = FriendsBlock.new
26   - block.expects(:owner).returns(p1)
27   -
28   - assert_equivalent [p2, p3, p4], block.profiles
29   - end
30   -
31   - should 'point to list with all friends' do
32   - block = FriendsBlock.new
33   - user = mock
34   - user.expects(:identifier).returns('theuser')
35   - block.expects(:owner).returns(user)
36   -
37   - expects(:link_to).with('View all', :profile => 'theuser', :controller => 'profile', :action => 'friends')
38   -
39   - instance_eval(&block.footer)
40   - end
41   -
42   - should 'count number of owner friends' do
43   - p1 = create_user('testuser1').person
44   - p2 = create_user('testuser2').person
45   - p3 = create_user('testuser3').person
46   - p4 = create_user('testuser4').person
47   -
48   - p1.add_friend(p2)
49   - p1.add_friend(p3)
50   - p1.add_friend(p4)
51   -
52   - block = FriendsBlock.new
53   - block.expects(:owner).returns(p1)
54   -
55   - assert_equal 3, block.profile_count
56   - end
57   -
58   - should 'count number of public and private people' do
59   - owner = create_user('testuser1').person
60   - private_p = fast_create(Person, {:public_profile => false})
61   - public_p = fast_create(Person, {:public_profile => true})
62   -
63   - owner.add_friend(private_p)
64   - owner.add_friend(public_p)
65   -
66   - block = FriendsBlock.new
67   - block.expects(:owner).returns(owner)
68   -
69   - assert_equal 2, block.profile_count
70   - end
71   -
72   - should 'not count number of invisible people' do
73   - owner = create_user('testuser1').person
74   - private_p = fast_create(Person, {:visible => false})
75   - public_p = fast_create(Person, {:visible => true})
76   -
77   - owner.add_friend(private_p)
78   - owner.add_friend(public_p)
79   -
80   - block = FriendsBlock.new
81   - block.expects(:owner).returns(owner)
82   -
83   - assert_equal 1, block.profile_count
84   - end
85   -
86   -end
test/unit/members_block_test.rb
... ... @@ -1,62 +0,0 @@
1   -require File.dirname(__FILE__) + '/../test_helper'
2   -
3   -class MembersBlockTest < ActiveSupport::TestCase
4   -
5   - should 'inherit from ProfileListBlock' do
6   - assert_kind_of ProfileListBlock, MembersBlock.new
7   - end
8   -
9   - should 'describe itself' do
10   - assert_not_equal ProfileListBlock.description, MembersBlock.description
11   - end
12   -
13   - should 'provide a default title' do
14   - assert_not_equal ProfileListBlock.new.default_title, MembersBlock.new.default_title
15   - end
16   -
17   - should 'display members file' do
18   - community = fast_create(Community)
19   - block = MembersBlock.create
20   - block.expects(:owner).returns(community)
21   -
22   - self.expects(:render).with(:file => 'blocks/members', :locals => { :profile => community, :show_join_leave_button => false}).returns('file-with-members-list')
23   - assert_equal 'file-with-members-list', instance_eval(&block.footer)
24   - end
25   -
26   - should 'pick random members' do
27   - block = MembersBlock.new
28   -
29   - owner = mock
30   - block.expects(:owner).returns(owner)
31   -
32   - list = []
33   - owner.expects(:members).returns(list)
34   -
35   - assert_same list, block.profiles
36   - end
37   -
38   - should 'use logged-in to compose cache key' do
39   - person = fast_create(Person)
40   - community = fast_create(Community)
41   - block = MembersBlock.create
42   - block.expects(:owner).returns(community)
43   -
44   - assert_match(/-logged-in/,block.cache_key('en', person))
45   - end
46   -
47   - should 'use logged-in and member to compose cache key for members' do
48   - person = fast_create(Person)
49   - community = fast_create(Community)
50   - community.add_member person
51   - block = MembersBlock.create
52   - block.expects(:owner).returns(community)
53   -
54   - assert_match(/-logged-in-member/,block.cache_key('en', person))
55   - end
56   -
57   - should 'not change block cache key if user is nil' do
58   - block = MembersBlock.new
59   - assert_equal block.cache_key('en'), block.cache_key('en', nil)
60   - end
61   -
62   -end
test/unit/people_block_test.rb
... ... @@ -1,50 +0,0 @@
1   -require File.dirname(__FILE__) + '/../test_helper'
2   -
3   -class PeopleBlockTest < ActiveSupport::TestCase
4   -
5   - should 'inherit from ProfileListBlock' do
6   - assert_kind_of ProfileListBlock, PeopleBlock.new
7   - end
8   -
9   - should 'declare its default title' do
10   - assert_not_equal ProfileListBlock.new.default_title, PeopleBlock.new.default_title
11   - end
12   -
13   - should 'describe itself' do
14   - assert_not_equal ProfileListBlock.description, PeopleBlock.description
15   - end
16   -
17   - should 'give help' do
18   - assert_not_equal ProfileListBlock.new.help, PeopleBlock.new.help
19   - end
20   -
21   - should 'list people' do
22   - owner = fast_create(Environment)
23   - block = PeopleBlock.new
24   - block.expects(:owner).returns(owner).at_least_once
25   - person1 = fast_create(Person, :environment_id => owner.id)
26   - person2 = fast_create(Person, :environment_id => owner.id)
27   -
28   - expects(:profile_image_link).with(person1, :minor).returns(person1.name)
29   - expects(:profile_image_link).with(person2, :minor).returns(person2.name)
30   - expects(:block_title).with(anything).returns('')
31   -
32   - content = instance_eval(&block.content)
33   -
34   - assert_match(/#{person1.name}/, content)
35   - assert_match(/#{person2.name}/, content)
36   - end
37   -
38   - should 'link to browse people' do
39   - block = PeopleBlock.new
40   - block.stubs(:owner).returns(Environment.default)
41   -
42   - expects(:_).with('View all').returns('View all people')
43   - expects(:link_to).with('View all people', :controller => 'search', :action => 'people')
44   - instance_eval(&block.footer)
45   - end
46   -
47   - protected
48   - include NoosferoTestHelper
49   -
50   -end
test/unit/tiny_mce_article_test.rb
... ... @@ -8,7 +8,7 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
8 8 @profile = create_user('zezinho').person
9 9 end
10 10 attr_reader :profile
11   -
  11 +
12 12 # this test can be removed when we get real tests for TinyMceArticle
13 13 should 'be an article' do
14 14 assert_subclass TextArticle, TinyMceArticle
... ... @@ -210,7 +210,7 @@ end
210 210 assert_equal true, a.notifiable?
211 211 assert_equal true, a.advertise?
212 212 assert_equal true, a.is_trackable?
213   -
  213 +
214 214 a.published=false
215 215 assert_equal false, a.published?
216 216 assert_equal false, a.is_trackable?
... ... @@ -237,4 +237,13 @@ end
237 237 assert_tag_in_string article.body, :tag => 'source', :attributes => {:src => 'http://example.ogv', :type => 'video/ogg'}
238 238 end
239 239  
  240 + should 'not sanitize colspan and rowspan attributes' do
  241 + article = TinyMceArticle.create!(:name => 'table with colspan and rowspan',
  242 + :body => "<table colspan='2' rowspan='3'><tr></tr></table>",
  243 + :profile => profile
  244 + )
  245 + assert_tag_in_string article.body, :tag => 'table',
  246 + :attributes => { :colspan => 2, :rowspan => 3 }
  247 + end
  248 +
240 249 end
... ...
vendor/plugins/acts_as_list/Rakefile 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +require 'rake'
  2 +require 'rake/testtask'
  3 +
  4 +desc 'Default: run acts_as_list unit tests.'
  5 +task :default => :test
  6 +
  7 +desc 'Test the acts_as_ordered_tree plugin.'
  8 +Rake::TestTask.new(:test) do |t|
  9 + t.libs << 'lib'
  10 + t.pattern = 'test/**/*_test.rb'
  11 + t.verbose = true
  12 +end
... ...
vendor/plugins/acts_as_list/lib/active_record/acts/list.rb
... ... @@ -26,8 +26,8 @@ module ActiveRecord
26 26 # Configuration options are:
27 27 #
28 28 # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
29   - # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
30   - # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
  29 + # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
  30 + # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
31 31 # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
32 32 # Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
33 33 def acts_as_list(options = {})
... ... @@ -39,11 +39,16 @@ module ActiveRecord
39 39 if configuration[:scope].is_a?(Symbol)
40 40 scope_condition_method = %(
41 41 def scope_condition
42   - if #{configuration[:scope].to_s}.nil?
43   - "#{configuration[:scope].to_s} IS NULL"
44   - else
45   - "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
  42 + self.class.send(:sanitize_sql_hash_for_conditions, { :#{configuration[:scope].to_s} => send(:#{configuration[:scope].to_s}) })
  43 + end
  44 + )
  45 + elsif configuration[:scope].is_a?(Array)
  46 + scope_condition_method = %(
  47 + def scope_condition
  48 + attrs = %w(#{configuration[:scope].join(" ")}).inject({}) do |memo,column|
  49 + memo[column.intern] = send(column.intern); memo
46 50 end
  51 + self.class.send(:sanitize_sql_hash_for_conditions, attrs)
47 52 end
48 53 )
49 54 else
... ... @@ -63,7 +68,7 @@ module ActiveRecord
63 68  
64 69 #{scope_condition_method}
65 70  
66   - before_destroy :remove_from_list
  71 + before_destroy :decrement_positions_on_lower_items
67 72 before_create :add_to_list_bottom
68 73 EOV
69 74 end
... ... @@ -250,7 +255,7 @@ module ActiveRecord
250 255 increment_positions_on_lower_items(position)
251 256 self.update_attribute(position_column, position)
252 257 end
253   - end
  258 + end
254 259 end
255 260 end
256 261 end
... ...
vendor/plugins/acts_as_list/test/list_test.rb
... ... @@ -6,14 +6,15 @@ require &#39;active_record&#39;
6 6  
7 7 require "#{File.dirname(__FILE__)}/../init"
8 8  
9   -ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
  9 +ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
10 10  
11 11 def setup_db
12 12 ActiveRecord::Schema.define(:version => 1) do
13 13 create_table :mixins do |t|
14 14 t.column :pos, :integer
15 15 t.column :parent_id, :integer
16   - t.column :created_at, :datetime
  16 + t.column :parent_type, :string
  17 + t.column :created_at, :datetime
17 18 t.column :updated_at, :datetime
18 19 end
19 20 end
... ... @@ -46,6 +47,11 @@ class ListWithStringScopeMixin &lt; ActiveRecord::Base
46 47 def self.table_name() "mixins" end
47 48 end
48 49  
  50 +class ArrayScopeListMixin < Mixin
  51 + acts_as_list :column => "pos", :scope => [:parent_id, :parent_type]
  52 +
  53 + def self.table_name() "mixins" end
  54 +end
49 55  
50 56 class ListTest < Test::Unit::TestCase
51 57  
... ... @@ -95,7 +101,7 @@ class ListTest &lt; Test::Unit::TestCase
95 101  
96 102 def test_injection
97 103 item = ListMixin.new(:parent_id => 1)
98   - assert_equal "parent_id = 1", item.scope_condition
  104 + assert_equal '"mixins"."parent_id" = 1', item.scope_condition
99 105 assert_equal "pos", item.position_column
100 106 end
101 107  
... ... @@ -187,40 +193,60 @@ class ListTest &lt; Test::Unit::TestCase
187 193 new2.move_higher
188 194 assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
189 195 end
190   -
191   -
192   - def test_remove_from_list_should_then_fail_in_list?
  196 +
  197 + def test_remove_from_list_should_then_fail_in_list?
193 198 assert_equal true, ListMixin.find(1).in_list?
194 199 ListMixin.find(1).remove_from_list
195 200 assert_equal false, ListMixin.find(1).in_list?
196   - end
197   -
198   - def test_remove_from_list_should_set_position_to_nil
  201 + end
  202 +
  203 + def test_remove_from_list_should_set_position_to_nil
199 204 assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
200   -
201   - ListMixin.find(2).remove_from_list
202   -
  205 +
  206 + ListMixin.find(2).remove_from_list
  207 +
203 208 assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
204   -
  209 +
205 210 assert_equal 1, ListMixin.find(1).pos
206 211 assert_equal nil, ListMixin.find(2).pos
207 212 assert_equal 2, ListMixin.find(3).pos
208 213 assert_equal 3, ListMixin.find(4).pos
209   - end
210   -
211   - def test_remove_before_destroy_does_not_shift_lower_items_twice
  214 + end
  215 +
  216 + def test_remove_before_destroy_does_not_shift_lower_items_twice
212 217 assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
213   -
214   - ListMixin.find(2).remove_from_list
215   - ListMixin.find(2).destroy
216   -
  218 +
  219 + ListMixin.find(2).remove_from_list
  220 + ListMixin.find(2).destroy
  221 +
217 222 assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
218   -
  223 +
  224 + assert_equal 1, ListMixin.find(1).pos
  225 + assert_equal 2, ListMixin.find(3).pos
  226 + assert_equal 3, ListMixin.find(4).pos
  227 + end
  228 +
  229 + def test_before_destroy_callbacks_do_not_update_position_to_nil_before_deleting_the_record
  230 + assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
  231 +
  232 + # We need to trigger all the before_destroy callbacks without actually
  233 + # destroying the record so we can see the affect the callbacks have on
  234 + # the record.
  235 + list = ListMixin.find(2)
  236 + if list.respond_to?(:run_callbacks)
  237 + list.run_callbacks(:destroy)
  238 + else
  239 + list.send(:callback, :before_destroy)
  240 + end
  241 +
  242 + assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
  243 +
219 244 assert_equal 1, ListMixin.find(1).pos
  245 + assert_equal 2, ListMixin.find(2).pos
220 246 assert_equal 2, ListMixin.find(3).pos
221 247 assert_equal 3, ListMixin.find(4).pos
222   - end
223   -
  248 + end
  249 +
224 250 end
225 251  
226 252 class ListSubTest < Test::Unit::TestCase
... ... @@ -271,7 +297,7 @@ class ListSubTest &lt; Test::Unit::TestCase
271 297  
272 298 def test_injection
273 299 item = ListMixin.new("parent_id"=>1)
274   - assert_equal "parent_id = 1", item.scope_condition
  300 + assert_equal '"mixins"."parent_id" = 1', item.scope_condition
275 301 assert_equal "pos", item.position_column
276 302 end
277 303  
... ... @@ -330,3 +356,165 @@ class ListSubTest &lt; Test::Unit::TestCase
330 356 end
331 357  
332 358 end
  359 +
  360 +class ArrayScopeListTest < Test::Unit::TestCase
  361 +
  362 + def setup
  363 + setup_db
  364 + (1..4).each { |counter| ArrayScopeListMixin.create! :pos => counter, :parent_id => 5, :parent_type => 'ParentClass' }
  365 + end
  366 +
  367 + def teardown
  368 + teardown_db
  369 + end
  370 +
  371 + def test_reordering
  372 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  373 +
  374 + ArrayScopeListMixin.find(2).move_lower
  375 + assert_equal [1, 3, 2, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  376 +
  377 + ArrayScopeListMixin.find(2).move_higher
  378 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  379 +
  380 + ArrayScopeListMixin.find(1).move_to_bottom
  381 + assert_equal [2, 3, 4, 1], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  382 +
  383 + ArrayScopeListMixin.find(1).move_to_top
  384 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  385 +
  386 + ArrayScopeListMixin.find(2).move_to_bottom
  387 + assert_equal [1, 3, 4, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  388 +
  389 + ArrayScopeListMixin.find(4).move_to_top
  390 + assert_equal [4, 1, 3, 2], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  391 + end
  392 +
  393 + def test_move_to_bottom_with_next_to_last_item
  394 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  395 + ArrayScopeListMixin.find(3).move_to_bottom
  396 + assert_equal [1, 2, 4, 3], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  397 + end
  398 +
  399 + def test_next_prev
  400 + assert_equal ArrayScopeListMixin.find(2), ArrayScopeListMixin.find(1).lower_item
  401 + assert_nil ArrayScopeListMixin.find(1).higher_item
  402 + assert_equal ArrayScopeListMixin.find(3), ArrayScopeListMixin.find(4).higher_item
  403 + assert_nil ArrayScopeListMixin.find(4).lower_item
  404 + end
  405 +
  406 + def test_injection
  407 + item = ArrayScopeListMixin.new(:parent_id => 1, :parent_type => 'ParentClass')
  408 + assert_equal '"mixins"."parent_id" = 1 AND "mixins"."parent_type" = \'ParentClass\'', item.scope_condition
  409 + assert_equal "pos", item.position_column
  410 + end
  411 +
  412 + def test_insert
  413 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  414 + assert_equal 1, new.pos
  415 + assert new.first?
  416 + assert new.last?
  417 +
  418 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  419 + assert_equal 2, new.pos
  420 + assert !new.first?
  421 + assert new.last?
  422 +
  423 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  424 + assert_equal 3, new.pos
  425 + assert !new.first?
  426 + assert new.last?
  427 +
  428 + new = ArrayScopeListMixin.create(:parent_id => 0, :parent_type => 'ParentClass')
  429 + assert_equal 1, new.pos
  430 + assert new.first?
  431 + assert new.last?
  432 + end
  433 +
  434 + def test_insert_at
  435 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  436 + assert_equal 1, new.pos
  437 +
  438 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  439 + assert_equal 2, new.pos
  440 +
  441 + new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  442 + assert_equal 3, new.pos
  443 +
  444 + new4 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  445 + assert_equal 4, new4.pos
  446 +
  447 + new4.insert_at(3)
  448 + assert_equal 3, new4.pos
  449 +
  450 + new.reload
  451 + assert_equal 4, new.pos
  452 +
  453 + new.insert_at(2)
  454 + assert_equal 2, new.pos
  455 +
  456 + new4.reload
  457 + assert_equal 4, new4.pos
  458 +
  459 + new5 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
  460 + assert_equal 5, new5.pos
  461 +
  462 + new5.insert_at(1)
  463 + assert_equal 1, new5.pos
  464 +
  465 + new4.reload
  466 + assert_equal 5, new4.pos
  467 + end
  468 +
  469 + def test_delete_middle
  470 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  471 +
  472 + ArrayScopeListMixin.find(2).destroy
  473 +
  474 + assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  475 +
  476 + assert_equal 1, ArrayScopeListMixin.find(1).pos
  477 + assert_equal 2, ArrayScopeListMixin.find(3).pos
  478 + assert_equal 3, ArrayScopeListMixin.find(4).pos
  479 +
  480 + ArrayScopeListMixin.find(1).destroy
  481 +
  482 + assert_equal [3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  483 +
  484 + assert_equal 1, ArrayScopeListMixin.find(3).pos
  485 + assert_equal 2, ArrayScopeListMixin.find(4).pos
  486 + end
  487 +
  488 + def test_remove_from_list_should_then_fail_in_list?
  489 + assert_equal true, ArrayScopeListMixin.find(1).in_list?
  490 + ArrayScopeListMixin.find(1).remove_from_list
  491 + assert_equal false, ArrayScopeListMixin.find(1).in_list?
  492 + end
  493 +
  494 + def test_remove_from_list_should_set_position_to_nil
  495 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  496 +
  497 + ArrayScopeListMixin.find(2).remove_from_list
  498 +
  499 + assert_equal [2, 1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  500 +
  501 + assert_equal 1, ArrayScopeListMixin.find(1).pos
  502 + assert_equal nil, ArrayScopeListMixin.find(2).pos
  503 + assert_equal 2, ArrayScopeListMixin.find(3).pos
  504 + assert_equal 3, ArrayScopeListMixin.find(4).pos
  505 + end
  506 +
  507 + def test_remove_before_destroy_does_not_shift_lower_items_twice
  508 + assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  509 +
  510 + ArrayScopeListMixin.find(2).remove_from_list
  511 + ArrayScopeListMixin.find(2).destroy
  512 +
  513 + assert_equal [1, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
  514 +
  515 + assert_equal 1, ArrayScopeListMixin.find(1).pos
  516 + assert_equal 2, ArrayScopeListMixin.find(3).pos
  517 + assert_equal 3, ArrayScopeListMixin.find(4).pos
  518 + end
  519 +
  520 +end
... ...