Commit 6c7a6cc3279057c7cdf972ff9a328f61de31e58b

Authored by Victor Costa
2 parents 3ebc0a24 88d13891

Merge branch 'suggest_article_refactor' into api

Showing 54 changed files with 446 additions and 208 deletions   Show diff stats
app/controllers/my_profile/cms_controller.rb
... ... @@ -350,7 +350,8 @@ class CmsController < MyProfileController
350 350 @task.ip_address = request.remote_ip
351 351 @task.user_agent = request.user_agent
352 352 @task.referrer = request.referrer
353   - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save
  353 + @task.requestor = current_person if logged_in?
  354 + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save
354 355 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
355 356 redirect_to @back_to
356 357 end
... ...
app/controllers/public/events_controller.rb
... ... @@ -5,7 +5,11 @@ class EventsController < PublicController
5 5  
6 6 def events
7 7 @events = []
8   - @date = build_date(params[:year], params[:month], params[:day])
  8 + begin
  9 + @date = build_date params[:year], params[:month], params[:day]
  10 + rescue ArgumentError # invalid date
  11 + return render_not_found
  12 + end
9 13  
10 14 if !params[:year] && !params[:month] && !params[:day]
11 15 @events = profile.events.next_events_from_month(@date).paginate(:per_page => per_page, :page => params[:page])
... ...
app/controllers/public/search_controller.rb
... ... @@ -62,7 +62,7 @@ class SearchController < PublicController
62 62 end
63 63  
64 64 def articles
65   - @scope = @environment.articles.public.paginate(paginate_options)
  65 + @scope = @environment.articles.public
66 66 full_text_search
67 67 end
68 68  
... ... @@ -76,7 +76,7 @@ class SearchController < PublicController
76 76 end
77 77  
78 78 def products
79   - @scope = @environment.products.paginate(paginate_options)
  79 + @scope = @environment.products
80 80 full_text_search
81 81 end
82 82  
... ... @@ -244,7 +244,7 @@ class SearchController < PublicController
244 244 def visible_profiles(klass, *extra_relations)
245 245 relations = [:image, :domains, :environment, :preferred_domain]
246 246 relations += extra_relations
247   - @environment.send(klass.name.underscore.pluralize).visible.includes(relations).paginate(paginate_options)
  247 + @environment.send(klass.name.underscore.pluralize).visible.includes(relations)
248 248 end
249 249  
250 250 def per_page
... ...
app/helpers/blog_helper.rb
... ... @@ -17,28 +17,28 @@ module BlogHelper
17 17 _('Configure blog')
18 18 end
19 19  
20   - def list_posts(articles, format = 'full', paginate = true)
  20 + def list_posts(articles, conf = { format: 'full', paginate: true })
21 21 pagination = will_paginate(articles, {
22 22 :param_name => 'npage',
23 23 :previous_label => _('« Newer posts'),
24 24 :next_label => _('Older posts »'),
25 25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
26   - }) if articles.present? && paginate
  26 + }) if articles.present? && conf[:paginate]
27 27 content = []
28 28 artic_len = articles.length
29 29 articles.each_with_index{ |art,i|
30   - css_add = [ 'position-'+(i+1).to_s() ]
  30 + css_add = [ 'blog-post', 'position-'+(i+1).to_s() ]
31 31 position = (i%2 == 0) ? 'odd-post' : 'even-post'
32 32 css_add << 'first' if i == 0
33 33 css_add << 'last' if i == (artic_len-1)
34 34 css_add << 'not-published' if !art.published?
35   - css_add << position + '-inner'
36   - content << content_tag('div',
37   - content_tag('div',
38   - display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe,
39   - :class => 'blog-post ' + css_add.join(' '),
40   - :id => "post-#{art.id}"), :class => position
41   - )
  35 + css_add << position
  36 + content << (content_tag 'div', id: "post-#{art.id}", class: css_add do
  37 + content_tag 'div', class: position + '-inner blog-post-inner' do
  38 + display_post(art, conf[:format]).html_safe +
  39 + '<br style="clear:both"/>'.html_safe
  40 + end
  41 + end)
42 42 }
43 43 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
44 44 end
... ... @@ -46,7 +46,16 @@ module BlogHelper
46 46 def display_post(article, format = 'full')
47 47 no_comments = (format == 'full') ? false : true
48 48 title = article_title(article, :no_comments => no_comments)
49   - html = send("display_#{format}_format", FilePresenter.for(article)).html_safe
  49 + method = "display_#{format.split('+')[0]}_format"
  50 + html = send(method, FilePresenter.for(article)).html_safe
  51 + if format.split('+')[1] == 'pic'
  52 + img = article.first_image
  53 + if img.blank?
  54 + '<div class="post-pic empty"></div>'
  55 + else
  56 + '<div class="post-pic" style="background-image:url('+img+')"></div>'
  57 + end
  58 + end.to_s +
50 59 title + html
51 60 end
52 61  
... ...
app/helpers/boxes_helper.rb
... ... @@ -251,8 +251,8 @@ module BoxesHelper
251 251 content_tag('h2', _('Embed block code')) +
252 252 content_tag('div', _('Below, you''ll see a field containing embed code for the block. Just copy the code and paste it into your website or blogging software.'), :style => 'margin-bottom: 1em;') +
253 253 content_tag('textarea', embed_code, :style => 'margin-bottom: 1em; width:100%; height:40%;', :readonly => 'readonly') +
254   - thickbox_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
255   - buttons << thickbox_inline_popup_icon(:embed, _('Embed code'), {}, "embed-code-box-#{block.id}") << html
  254 + modal_close_button(_('Close')), :style => 'display: none;', :id => "embed-code-box-#{block.id}")
  255 + buttons << modal_inline_icon(:embed, _('Embed code'), {}, "#embed-code-box-#{block.id}") << html
256 256 end
257 257  
258 258 content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
... ...
app/helpers/tinymce_helper.rb
... ... @@ -17,6 +17,7 @@ module TinymceHelper
17 17 searchreplace wordcount visualblocks visualchars code fullscreen
18 18 insertdatetime media nonbreaking save table contextmenu directionality
19 19 emoticons template paste textcolor colorpicker textpattern],
  20 + :image_advtab => true,
20 21 :language => tinymce_language
21 22  
22 23 options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
... ...
app/models/article.rb
... ... @@ -5,7 +5,7 @@ class Article &lt; ActiveRecord::Base
5 5 :allow_members_to_edit, :translation_of_id, :language,
6 6 :license_id, :parent_id, :display_posts_in_current_language,
7 7 :category_ids, :posts_per_page, :moderate_comments,
8   - :accept_comments, :feed, :published, :source,
  8 + :accept_comments, :feed, :published, :source, :source_name,
9 9 :highlighted, :notify_comments, :display_hits, :slug,
10 10 :external_feed_builder, :display_versions, :external_link,
11 11 :image_builder, :show_to_followers
... ... @@ -784,7 +784,9 @@ class Article &lt; ActiveRecord::Base
784 784 end
785 785  
786 786 def first_image
787   - img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  787 + img = ( image.present? && { 'src' => image.public_filename } ) ||
  788 + Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  789 + Nokogiri::HTML.fragment(self.body.to_s).search('img').first
788 790 img.nil? ? '' : img['src']
789 791 end
790 792  
... ...
app/models/blog.rb
... ... @@ -76,7 +76,7 @@ class Blog &lt; Folder
76 76 end
77 77  
78 78 settings_items :visualization_format, :type => :string, :default => 'full'
79   - validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format
  79 + validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format
80 80  
81 81 settings_items :display_posts_in_current_language, :type => :boolean, :default => false
82 82  
... ...
app/models/suggest_article.rb
1 1 class SuggestArticle < Task
2 2  
3   - validates_presence_of :target_id, :article_name, :email, :name, :article_body
  3 + validates_presence_of :target_id
  4 + validates_presence_of :email, :name, :if => Proc.new { |task| task.requestor.blank? }
  5 + validates_associated :article_object
4 6  
5 7 settings_items :email, :type => String
6 8 settings_items :name, :type => String
7   - settings_items :article_name, :type => String
8   - settings_items :article_body, :type => String
9   - settings_items :article_abstract, :type => String
10   - settings_items :article_parent_id, :type => String
11   - settings_items :source, :type => String
12   - settings_items :source_name, :type => String
13   - settings_items :highlighted, :type => :boolean, :default => false
14 9 settings_items :ip_address, :type => String
15 10 settings_items :user_agent, :type => String
16 11 settings_items :referrer, :type => String
  12 + settings_items :article, :type => Hash, :default => {}
17 13  
18 14 after_create :schedule_spam_checking
19 15  
... ... @@ -24,34 +20,45 @@ class SuggestArticle &lt; Task
24 20 include Noosfero::Plugin::HotSpot
25 21  
26 22 def sender
27   - "#{name} (#{email})"
  23 + requestor ? "#{requestor.name}" : "#{name} (#{email})"
  24 + end
  25 +
  26 + def article_object
  27 + if @article_object.nil?
  28 + @article_object = article_type.new(article.merge({:profile => target}))
  29 + if requestor.present?
  30 + @article_object.author = requestor
  31 + else
  32 + @article_object.author_name = name
  33 + end
  34 + end
  35 + @article_object
  36 + end
  37 +
  38 + def article_type
  39 + (article[:type] || 'TinyMceArticle').constantize
28 40 end
29 41  
30 42 def perform
31   - task = TinyMceArticle.new
32   - task.profile = target
33   - task.name = article_name
34   - task.author_name = name
35   - task.body = article_body
36   - task.abstract = article_abstract
37   - task.parent_id = article_parent_id
38   - task.source = source
39   - task.source_name = source_name
40   - task.highlighted = highlighted
41   - task.save!
  43 + article_object.save!
42 44 end
43 45  
44 46 def title
45 47 _("Article suggestion")
46 48 end
47 49  
  50 + def article_name
  51 + article[:name]
  52 + end
  53 +
48 54 def subject
49 55 article_name
50 56 end
51 57  
52 58 def information
53   - { :message => _('%{sender} suggested the publication of the article: %{subject}.'),
54   - :variables => {:sender => sender} }
  59 + variables = requestor.blank? ? {:requestor => sender} : {}
  60 + { :message => _('%{requestor} suggested the publication of the article: %{subject}.'),
  61 + :variables => variables }
55 62 end
56 63  
57 64 def accept_details
... ... @@ -63,8 +70,8 @@ class SuggestArticle &lt; Task
63 70 end
64 71  
65 72 def target_notification_description
66   - _('%{sender} suggested the publication of the article: %{article}.') %
67   - {:sender => sender, :article => article_name}
  73 + _('%{requestor} suggested the publication of the article: %{article}.') %
  74 + {:requestor => sender, :article => article_name}
68 75 end
69 76  
70 77 def target_notification_message
... ...
app/models/user.rb
... ... @@ -46,7 +46,7 @@ class User &lt; ActiveRecord::Base
46 46 p = Person.new
47 47  
48 48 p.attributes = user.person_data
49   - p.identifier = user.login
  49 + p.identifier = user.login if p.identifier.blank?
50 50 p.user = user
51 51 p.environment = user.environment
52 52 p.name ||= user.name || user.login
... ...
app/views/cms/_blog.html.erb
... ... @@ -64,7 +64,11 @@
64 64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%>
65 65 <% end %>
66 66  
67   -<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %>
  67 +<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
  68 + [ _('Full post'), 'full'],
  69 + [ _('First paragraph'), 'short'],
  70 + [ _('First paragraph, with post picture'), 'short+pic']
  71 +])) %>
68 72  
69 73 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
70 74  
... ...
app/views/cms/suggest_an_article.html.erb
... ... @@ -6,21 +6,22 @@
6 6  
7 7 <%= labelled_form_for 'task' do |f| %>
8 8  
9   - <%= required labelled_form_field(_('Title'), text_field(:task, 'article_name', :size => 50)) %>
  9 + <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %>
10 10  
11   - <%= labelled_form_field(_('Source'), text_field(:task, 'source_name')) %>
  11 + <%= labelled_form_field(_('Source'), text_field('task[article]', 'source_name')) %>
12 12  
13   - <%= labelled_form_field(_('Source URL'), text_field(:task, 'source')) %>
  13 + <%= labelled_form_field(_('Source URL'), text_field('task[article]', 'source')) %>
14 14  
15   - <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
16   -
17   - <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  15 + <% unless logged_in? %>
  16 + <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
  17 + <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  18 + <% end %>
18 19  
19   - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %>
  20 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %>
20 21  
21 22 <%= hidden_field_tag('back_to', @back_to) %>
22 23  
23   - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
  24 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
24 25  
25 26 <% button_bar do %>
26 27 <%= submit_button :save, _('Save') %>
... ...
app/views/content_viewer/blog_page.html.erb
... ... @@ -18,6 +18,9 @@
18 18 format = inside_block.visualization_format
19 19 paginate = false
20 20 end
21   - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate))
  21 + (blog.empty? ?
  22 + content_tag('em', _('(no posts)')) :
  23 + list_posts(posts, format: format, paginate: paginate)
  24 + )
22 25 %>
23 26 </div>
... ...
app/views/profile/report_abuse.html.erb
... ... @@ -24,7 +24,7 @@
24 24 $('#report-abuse-submit-button').css('cursor', 'progress');
25 25 $.ajax({
26 26 type: 'POST',
27   - url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}) %>,
  27 + url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}).to_json %>,
28 28 data: $(form).serialize(),
29 29 dataType: 'json',
30 30 success: function(data, status, ajax){
... ...
app/views/profile_editor/edit.html.erb
1 1 <h1><%= _('Profile settings for %s') % profile.name %></h1>
2 2  
3   -<%= javascript_include_tag 'deactivate_profile' %>
4 3 <%= error_messages_for :profile_data %>
5 4  
6 5 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %>
... ...
app/views/search/search.js.erb
1   -jQuery('#search-content').html('<%= escape_javascript(render :partial => "search_content") %>');
  1 +jQuery('#search-content').replaceWith('<%= escape_javascript(render "search_content") %>');
  2 +
... ...
app/views/spam/_suggest_article.html.erb
... ... @@ -7,13 +7,13 @@
7 7 <ul class="suggest-article-details" style="display: none">
8 8 <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li>
9 9 <li><strong><%=_('Email')%></strong>: <%=task.email%> </li>
10   - <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li>
11   - <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li>
12   - <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>
13   - <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li>
  10 + <li><strong><%=_('Source')%></strong>: <%=task.article_object.source_name%> </li>
  11 + <li><strong><%=_('Source URL')%></strong>: <%=task.article_object.source%> </li>
  12 + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_object.parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>
  13 + <li><strong><%=_('Lead')%></strong>: <%=task.article_object.abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_object.abstract%> </li>
14 14 <li><strong><%=_('Body')%></strong>:
15 15 <div class='suggest-article-body'>
16   - <%= task.article_body %>
  16 + <%= task.article_object.body %>
17 17 </div>
18 18 </li>
19 19 </ul>
... ...
app/views/tasks/_suggest_article_accept_details.html.erb
1 1 <%= render :file => 'shared/tiny_mce' %>
2 2  
3   -<%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
4   -<p><%= label_tag(_("Email: %s") % task.email) %> </p>
5   -<%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %>
6   -<%= labelled_form_field(_('Source'), f.text_field(:source_name)) %>
7   -<%= labelled_form_field(_("Source URL"), f.text_field(:source)) %>
  3 +<% unless task.requestor %>
  4 + <%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
  5 + <p><%= label_tag(_("Email: %s") % task.email) %> </p>
  6 +<% end %>
8 7  
9   -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %>
10   -<%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %>
  8 +<%= f.fields_for 'article', OpenStruct.new(task.article) do |a| %>
  9 + <%= required labelled_form_field(_('Title'), a.text_field(:name, :size => 50)) %>
  10 + <%= labelled_form_field(_('Source'), a.text_field(:source_name)) %>
  11 + <%= labelled_form_field(_("Source URL"), a.text_field(:source)) %>
11 12  
12   -<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %>
  13 + <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article][parent_id]", task.target) %>
  14 + <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %>
  15 +
  16 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %>
  17 +<% end %>
... ...
config/initializers/newrelic.rb
... ... @@ -1,2 +0,0 @@
1   -# Load newrelic agent if its config file is defined.
2   -require 'newrelic_rpm' if File.exist?(File.dirname(__FILE__) + '/../newrelic.yml')
db/migrate/20140724134601_fix_yaml_encoding.rb
... ... @@ -18,9 +18,8 @@ class FixYamlEncoding &lt; ActiveRecord::Migration
18 18 private
19 19  
20 20 def self.fix_encoding(model, param)
21   - result = model.all
22   - puts "Fixing #{result.count} rows of #{model} (#{param})"
23   - result.each do |r|
  21 + puts "Fixing #{model.count} rows of #{model} (#{param})"
  22 + model.find_each do |r|
24 23 begin
25 24 yaml = r.send(param)
26 25 # if deserialization failed then a string is returned
... ...
debian/changelog
  1 +noosfero (1.1~rc4) wheezy; urgency=medium
  2 +
  3 + * Fourth release candidate for Noosfero 1.1
  4 +
  5 + -- Antonio Terceiro <terceiro@debian.org> Wed, 01 Apr 2015 12:22:36 -0300
  6 +
1 7 noosfero (1.1~rc2) wheezy; urgency=low
2 8  
3 9 * Second release candidate for Noosfero 1.1
... ...
debian/noosfero.install
... ... @@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d
25 25 etc/logrotate.d/noosfero etc/logrotate.d
26 26 etc/noosfero/varnish-accept-language.vcl etc/noosfero
27 27 etc/noosfero/varnish-noosfero.vcl etc/noosfero
  28 +etc/awstats-noosfero.conf etc/noosfero
28 29 lib usr/share/noosfero
29 30 locale usr/share/noosfero
30 31 plugins usr/share/noosfero
... ...
features/edit_article.feature
... ... @@ -250,6 +250,7 @@ Feature: edit article
250 250 Scenario: add a translation to an article
251 251 Given I am on joaosilva's sitemap
252 252 And I follow "Save the whales"
  253 + And the following languages "en es" are available on environment
253 254 Then I should not see "Add translation"
254 255 And I follow "Edit"
255 256 And I select "English" from "Language"
... ... @@ -267,6 +268,7 @@ Feature: edit article
267 268 | owner | name | language |
268 269 | joaosilva | Article in English | en |
269 270 And I am on joaosilva's sitemap
  271 + And the following languages "en pt" are available on environment
270 272 When I follow "Article in English"
271 273 And I follow "Add translation"
272 274 And I fill in "Title" with "Article in Portuguese"
... ...
features/login.feature
... ... @@ -207,18 +207,3 @@ Feature: login
207 207 | Password | 123456 |
208 208 When I press "Log in"
209 209 Then I should be on joaosilva's control panel
210   -
211   - Scenario: join community on login
212   - Given the following users
213   - | login | name |
214   - | mariasilva | Maria Silva |
215   - And the following communities
216   - | name | identifier | owner |
217   - | Free Software | freesoftware | mariasilva |
218   - And I am on /freesoftware
219   - When I follow "Join"
220   - And I fill in the following:
221   - | Username / Email | joaosilva |
222   - | Password | 123456 |
223   - And I press "Log in"
224   - Then "Joao Silva" should be a member of "Free Software"
... ...
features/step_definitions/internationalization_steps.rb
... ... @@ -22,6 +22,10 @@ Given /^Noosfero is configured to use (.+) as default$/ do |lang|
22 22 Noosfero.default_locale = language_to_code(lang)
23 23 end
24 24  
  25 +Given /^the following languages "([^"]*)" are available on environment$/ do |languages|
  26 + Environment.default.update_attribute(:languages, languages.split)
  27 +end
  28 +
25 29 After do
26 30 # reset everything back to normal
27 31 Noosfero.default_locale = nil
... ...
lib/noosfero/plugin.rb
... ... @@ -8,6 +8,10 @@ class Noosfero::Plugin
8 8 self.context = context
9 9 end
10 10  
  11 + def environment
  12 + context.environment if self.context
  13 + end
  14 +
11 15 class << self
12 16  
13 17 attr_writer :should_load
... ... @@ -35,6 +39,7 @@ class Noosfero::Plugin
35 39 # filters must be loaded after all extensions
36 40 klasses.each do |plugin|
37 41 load_plugin_filters plugin
  42 + load_plugin_hotspots plugin
38 43 end
39 44 end
40 45  
... ... @@ -108,6 +113,23 @@ class Noosfero::Plugin
108 113 end
109 114 end
110 115  
  116 + # This is a generic method to extend the hotspots list with plugins
  117 + # hotspots. This allows plugins to extend other plugins.
  118 + # To use this, the plugin must define its hotspots inside a module Hotspots.
  119 + # Its also needed to include Noosfero::Plugin::HotSpot module
  120 + # in order to dispatch plugins methods.
  121 + #
  122 + # Checkout FooPlugin for usage example.
  123 + def load_plugin_hotspots(plugin)
  124 + ActionDispatch::Reloader.to_prepare do
  125 + begin
  126 + module_name = "#{plugin.name}::Hotspots"
  127 + Noosfero::Plugin.send(:include, module_name.constantize)
  128 + rescue NameError
  129 + end
  130 + end
  131 + end
  132 +
111 133 def add_controller_filters(controller_class, plugin, filters)
112 134 unless filters.is_a?(Array)
113 135 filters = [filters]
... ...
lib/noosfero/version.rb
1 1 module Noosfero
2 2 PROJECT = 'noosfero'
3   - VERSION = '1.1~rc2'
  3 + VERSION = '1.1~rc4'
4 4 end
5 5  
6 6 root = File.expand_path(File.dirname(__FILE__) + '/../..')
... ...
lib/tasks/plugins_tests.rake
... ... @@ -4,7 +4,6 @@ $broken_plugins = %w[
4 4 comment_classification
5 5 ldap
6 6 solr
7   - stoa
8 7 ]
9 8  
10 9 @all_plugins = Dir.glob('plugins/*').map { |f| File.basename(f) } - ['template']
... ...
plugins/context_content/lib/context_content_plugin/context_content_block.rb
... ... @@ -58,7 +58,7 @@ class ContextContentPlugin::ContextContentBlock &lt; Block
58 58 def contents(page, p=1)
59 59 return @children unless @children.blank?
60 60 if page
61   - @children = page.children.with_types(types).paginate(:per_page => limit, :page => p)
  61 + @children = page.children.with_types(types).order(:name).paginate(:per_page => limit, :page => p)
62 62 (@children.blank? && show_parent_content) ? contents(page.parent, p) : @children
63 63 else
64 64 nil
... ...
plugins/context_content/test/unit/context_content_block_test.rb
... ... @@ -51,18 +51,18 @@ class ContextContentBlockTest &lt; ActiveSupport::TestCase
51 51 should 'show contents for next page' do
52 52 @block.limit = 2
53 53 folder = fast_create(Folder)
54   - article1 = fast_create(TinyMceArticle, :parent_id => folder.id)
55   - article2 = fast_create(TinyMceArticle, :parent_id => folder.id)
56   - article3 = fast_create(TinyMceArticle, :parent_id => folder.id)
  54 + article1 = fast_create(TinyMceArticle, :name => 'article 1', :parent_id => folder.id)
  55 + article2 = fast_create(TinyMceArticle, :name => 'article 2', :parent_id => folder.id)
  56 + article3 = fast_create(TinyMceArticle, :name => 'article 3', :parent_id => folder.id)
57 57 assert_equal [article3], @block.contents(folder, 2)
58 58 end
59 59  
60 60 should 'show parent contents for next page' do
61 61 @block.limit = 2
62 62 folder = fast_create(Folder)
63   - article1 = fast_create(TinyMceArticle, :parent_id => folder.id)
64   - article2 = fast_create(TinyMceArticle, :parent_id => folder.id)
65   - article3 = fast_create(TinyMceArticle, :parent_id => folder.id)
  63 + article1 = fast_create(TinyMceArticle, :name => 'article 1', :parent_id => folder.id)
  64 + article2 = fast_create(TinyMceArticle, :name => 'article 2', :parent_id => folder.id)
  65 + article3 = fast_create(TinyMceArticle, :name => 'article 3', :parent_id => folder.id)
66 66 assert_equal [article3], @block.contents(article1, 2)
67 67 end
68 68  
... ...
plugins/foo/lib/foo_plugin.rb
1 1 class FooPlugin < Noosfero::Plugin
  2 + include Noosfero::Plugin::HotSpot
2 3  
3 4 def self.plugin_name
4 5 "Foo"
... ... @@ -8,12 +9,29 @@ class FooPlugin &lt; Noosfero::Plugin
8 9 _("A sample plugin to test autoload craziness.")
9 10 end
10 11  
  12 + module Hotspots
  13 + # -> Custom foo plugin hotspot
  14 + # do something to extend the FooPlugin behaviour
  15 + # receive params a, b and c
  16 + # returns = boolean or something else
  17 + def foo_plugin_my_hotspot(a, b, c)
  18 + end
  19 +
  20 + # -> Custom title for foo profiles tab
  21 + # returns = a string with a custom title
  22 + def foo_plugin_tab_title
  23 + end
  24 + end
  25 +
11 26 def control_panel_buttons
12 27 {:title => 'Foo plugin button', :icon => '', :url => ''}
13 28 end
14 29  
15 30 def profile_tabs
16   - {:title => 'Foo plugin tab', :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} }
  31 + title = plugins.dispatch_first(:foo_plugin_tab_title)
  32 + title = 'Foo plugin tab' unless title
  33 +
  34 + {:title => title, :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} }
17 35 end
18 36  
19 37 end
... ...
plugins/foo/test/unit/foo_plugin_test.rb
... ... @@ -4,7 +4,25 @@ class FooPluginTest &lt; ActiveSupport::TestCase
4 4 def test_foo
5 5 FooPlugin::Bar.create!
6 6 end
  7 +
7 8 def test_monkey_patch
8 9 Profile.new.bar
9 10 end
  11 +
  12 + should "respond to new hotspots" do
  13 + plugin = FooPlugin.new
  14 +
  15 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  16 + assert plugin.respond_to?(:foo_plugin_tab_title)
  17 + end
  18 +
  19 + should "other plugin respond to new hotspots" do
  20 + class TestPlugin < Noosfero::Plugin
  21 + end
  22 +
  23 + plugin = TestPlugin.new
  24 +
  25 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  26 + assert plugin.respond_to?(:foo_plugin_tab_title)
  27 + end
10 28 end
... ...
plugins/ldap/lib/ldap_authentication.rb
... ... @@ -77,18 +77,20 @@ class LdapAuthentication
77 77 end
78 78  
79 79 def get_user_attributes_from_ldap_entry(entry)
80   - {
81   - :dn => entry.dn,
82   - :fullname => LdapAuthentication.get_attr(entry, self.attr_fullname),
83   - :mail => LdapAuthentication.get_attr(entry, self.attr_mail),
84   - }
  80 + attributes = entry.instance_values["myhash"]
  81 +
  82 + attributes[:dn] = entry.dn
  83 + attributes[:fullname] = LdapAuthentication.get_attr(entry, self.attr_fullname)
  84 + attributes[:mail] = LdapAuthentication.get_attr(entry, self.attr_mail)
  85 +
  86 + attributes
85 87 end
86 88  
87 89 # Return the attributes needed for the LDAP search. It will only
88 90 # include the user attributes if on-the-fly registration is enabled
89 91 def search_attributes
90 92 if onthefly_register?
91   - ['dn', self.attr_fullname, self.attr_mail]
  93 + nil
92 94 else
93 95 ['dn']
94 96 end
... ... @@ -111,6 +113,7 @@ class LdapAuthentication
111 113 end
112 114 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
113 115 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
  116 +
114 117 attrs = {}
115 118  
116 119 search_filter = object_filter & login_filter
... ...
plugins/ldap/lib/ldap_plugin.rb
1 1 require File.dirname(__FILE__) + '/ldap_authentication.rb'
2 2  
3 3 class LdapPlugin < Noosfero::Plugin
  4 + include Noosfero::Plugin::HotSpot
4 5  
5 6 def self.plugin_name
6 7 "LdapPlugin"
... ... @@ -10,6 +11,25 @@ class LdapPlugin &lt; Noosfero::Plugin
10 11 _("A plugin that add ldap support.")
11 12 end
12 13  
  14 + module Hotspots
  15 + # -> Custom ldap plugin hotspot to set profile data before user creation
  16 + # receive the followings params:
  17 + # - attrs with ldap received data
  18 + # - login received by ldap
  19 + # - params from current context
  20 + # returns = updated person_data hash
  21 + def ldap_plugin_set_profile_data(attrs, login, params)
  22 + end
  23 +
  24 + # -> Custom ldap plugin hotspot to update user object
  25 + # receive the followings params:
  26 + # - user: user object
  27 + # - attrs with ldap received data
  28 + # returns = none
  29 + def ldap_plugin_update_user(user, attrs)
  30 + end
  31 + end
  32 +
13 33 def allow_user_registration
14 34 false
15 35 end
... ... @@ -39,13 +59,15 @@ class LdapPlugin &lt; Noosfero::Plugin
39 59 user.name = attrs[:fullname]
40 60 user.password = password
41 61 user.password_confirmation = password
42   - user.person_data = context.params[:profile_data]
  62 + person_data = plugins.dispatch(:ldap_plugin_set_profile_data, attrs, login, context.params)
  63 + user.person_data = person_data.blank? ? context.params[:profile_data] : person_data
43 64 user.activated_at = Time.now.utc
44 65 user.activation_code = nil
45 66  
46 67 ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes)
47 68 begin
48   - user = nil unless user.save
  69 + user = nil unless user.save!
  70 + plugins.dispatch(:ldap_plugin_update_user, user, attrs)
49 71 rescue
50 72 #User not saved
51 73 end
... ... @@ -54,7 +76,6 @@ class LdapPlugin &lt; Noosfero::Plugin
54 76 end
55 77  
56 78 else
57   -
58 79 return nil if !user.activated?
59 80  
60 81 begin
... ...
plugins/profile_description_block/test/unit/profile_description_block_test.rb
1 1 require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
2 2  
3 3 class ProfileDescriptionBlockTest < ActiveSupport::TestCase
4   - def setup
5   - e = Environment.default
  4 + def setup
  5 + e = Environment.default
6 6 e.enabled_plugins = ['ProfileDescriptionPlugin']
7 7 @person = create_user('test_user').person
8 8 @profile = Profile.create!(:identifier => '1236',
9 9 :name => 'blabla',
10 10 :description => "")
11   - end
  11 + end
12 12  
13 13 should 'describe itself' do
14 14 assert_not_equal Block.description, ProfileDescriptionBlock.description
... ... @@ -17,7 +17,7 @@ class ProfileDescriptionBlockTest &lt; ActiveSupport::TestCase
17 17 should "show profile description inside block" do
18 18 new_block = ProfileDescriptionBlock.create!
19 19 @profile.boxes.first.blocks << new_block
20   - block_menssage = "Description field are empty"
  20 + block_menssage = "Description field is empty"
21 21 assert (instance_eval(&Block.last.content).include?(block_menssage)),
22 22 "description block doesn't show not found description message"
23 23 description = "This is an test"
... ...
plugins/stoa/lib/stoa_plugin.rb
... ... @@ -60,13 +60,14 @@ class StoaPlugin &lt; Noosfero::Plugin
60 60 end
61 61  
62 62 def account_controller_filters
63   - block = lambda do |context|
  63 + block = proc do
64 64 params[:profile_data] ||= {}
65 65 params[:profile_data][:invitation_code] = params[:invitation_code]
66 66 invitation = Task.pending.find(:first, :conditions => {:code => params[:invitation_code]})
67 67 if request.post?
68 68 if !invitation && !StoaPlugin::UspUser.matches?(params[:profile_data][:usp_id], params[:confirmation_field], params[params[:confirmation_field]])
69   - @person = Person.new(:environment => context.environment)
  69 + # `self` below is evaluated in the context of account_controller
  70 + @person = Person.new(:environment => self.environment)
70 71 @person.errors.add(:usp_id, _(' validation failed'))
71 72 render :action => :signup
72 73 end
... ...
plugins/stoa/lib/stoa_plugin/person_api.rb
... ... @@ -16,7 +16,7 @@ class StoaPlugin::PersonApi &lt; Noosfero::FieldsDecorator
16 16 end
17 17  
18 18 def homepage
19   - context.url_for(url)
  19 + profile_homepage(context, object)
20 20 end
21 21  
22 22 def birth_date
... ... @@ -35,6 +35,16 @@ class StoaPlugin::PersonApi &lt; Noosfero::FieldsDecorator
35 35 end
36 36  
37 37 def communities
38   - object.communities.public.map {|community| {:url => context.url_for(community.url), :name => community.name}}
  38 + object.communities.public.map {|community| {:url => profile_homepage(context, community), :name => community.name}}
  39 + end
  40 +
  41 + private
  42 +
  43 + def profile_homepage(context, profile)
  44 + if context.respond_to?(:url_for)
  45 + context.url_for(profile.url)
  46 + else
  47 + profile.environment.top_url + '/' + profile.identifier
  48 + end
39 49 end
40 50 end
... ...
plugins/stoa/test/functional/invite_controller_test.rb
... ... @@ -57,7 +57,7 @@ class InviteControllerTest &lt; ActionController::TestCase
57 57 organization.add_admin(admin)
58 58  
59 59 login_as(admin.identifier)
60   - get :search_friend, :profile => organization.identifier, :q => '1234'
  60 + get :search, :profile => organization.identifier, :q => '1234'
61 61  
62 62 assert_equal [{"id" => person.id, "name" => person.name}].to_json, @response.body
63 63 assert_response 200
... ...
plugins/sub_organizations/features/sub_organizations_display.feature
... ... @@ -29,6 +29,7 @@ Feature: sub_organizations_display
29 29 And I follow "Manage sub-groups"
30 30 And I follow "Register a new sub-enterprise"
31 31 And I fill in "Name" with "Bart"
  32 + And I fill in "Address" with "bart"
32 33 And I press "Next"
33 34 Then I should see "Enterprise registration completed"
34 35 And I am logged in as admin
... ...
plugins/sub_organizations/lib/ext/create_enterprise.rb
... ... @@ -2,4 +2,5 @@ require_dependency &#39;create_enterprise&#39;
2 2  
3 3 class CreateEnterprise
4 4 settings_items :sub_organizations_plugin_parent_to_be
  5 + DATA_FIELDS << 'sub_organizations_plugin_parent_to_be'
5 6 end
... ...
po/pt/noosfero.po
... ... @@ -13,8 +13,8 @@ msgid &quot;&quot;
13 13 msgstr ""
14 14 "Project-Id-Version: 1.0-690-gcb6e853\n"
15 15 "POT-Creation-Date: 2015-03-05 12:10-0300\n"
16   -"PO-Revision-Date: 2015-03-17 21:44+0200\n"
17   -"Last-Translator: Evandro Junior <evandrojr@gmail.com>\n"
  16 +"PO-Revision-Date: 2015-03-29 01:47+0200\n"
  17 +"Last-Translator: daniel <dtygel@eita.org.br>\n"
18 18 "Language-Team: Portuguese "
19 19 "<https://hosted.weblate.org/projects/noosfero/noosfero/pt/>\n"
20 20 "Language: pt\n"
... ... @@ -7281,7 +7281,7 @@ msgstr &quot;Seu nome&quot;
7281 7281 #: app/views/cms/_upload_file_form.html.erb:4
7282 7282 #: app/views/cms/_text_editor_sidebar.html.erb:16
7283 7283 msgid "Choose folder to upload files:"
7284   -msgstr "Escolha uma pasta para incluir arquivos:"
  7284 +msgstr "O arquivo ficará na seguinte pasta:"
7285 7285  
7286 7286 #: app/views/cms/_upload_file_form.html.erb:16
7287 7287 msgid "More files"
... ... @@ -7535,7 +7535,7 @@ msgstr &quot;Houve problemas com os seguintes arquivos:&quot;
7535 7535  
7536 7536 #: app/views/cms/upload_files.html.erb:15
7537 7537 msgid "Publish media"
7538   -msgstr "Publicar mídia"
  7538 +msgstr "Publicar imagem ou documento"
7539 7539  
7540 7540 #: app/views/cms/upload_files.html.erb:17
7541 7541 msgid "Select the files you want to upload (max size %s):"
... ... @@ -7551,7 +7551,7 @@ msgstr &quot;Enviando arquivos para %s&quot;
7551 7551  
7552 7552 #: app/views/cms/_text_editor_sidebar.html.erb:8
7553 7553 msgid "Insert media"
7554   -msgstr "Adicionar mídia"
  7554 +msgstr "Adicionar imagem ou documento"
7555 7555  
7556 7556 #: app/views/cms/_text_editor_sidebar.html.erb:8
7557 7557 msgid "Show/Hide"
... ... @@ -7559,7 +7559,7 @@ msgstr &quot;Mostrar/Ocultar&quot;
7559 7559  
7560 7560 #: app/views/cms/_text_editor_sidebar.html.erb:21
7561 7561 msgid "New folder"
7562   -msgstr "Nova pasta"
  7562 +msgstr "Criar pasta"
7563 7563  
7564 7564 #: app/views/cms/_text_editor_sidebar.html.erb:26
7565 7565 msgid "Hide all uploads"
... ...
public/javascripts/report-abuse.js
1 1 jQuery(function($) {
2 2 $('.report-abuse-action').live('click', function() {
3   - if($(this).attr('href')){
4   - noosfero.modal.inline($(this).attr('href'), {
5   - innerHeight: '300px',
6   - innerWidth: '445px'
7   - });
8   - }
  3 + if($(this).attr('href'))
  4 + noosfero.modal.url($(this).attr('href'));
  5 +
9 6 return false;
10 7 });
11 8  
... ...
public/stylesheets/application.css
... ... @@ -1501,6 +1501,14 @@ a.comment-picture {
1501 1501 #content .title {
1502 1502 margin-bottom: 2px;
1503 1503 }
  1504 +.blog-post .post-pic {
  1505 + background-position: 50% 40%;
  1506 + background-size: cover;
  1507 + height: 150px;
  1508 +}
  1509 +.blog-post .post-pic.empty {
  1510 + display: none;
  1511 +}
1504 1512 .metadata, .blog-post .metadata {
1505 1513 display: block;
1506 1514 text-align: center;
... ...
script/production
... ... @@ -85,7 +85,7 @@ environments_loop() {
85 85 }
86 86  
87 87 do_running() {
88   - pids=$(cat tmp/pids/thin.*.pid 2>/dev/null || true)
  88 + pids=$(sed "s/.*/& /" tmp/pids/thin.*.pid | tr -d '\n' 2>/dev/null || true)
89 89 # passes if any of $pids exist, fails otherwise
90 90 kill -0 $pids > /dev/null 2>&1
91 91 }
... ...
test/factories.rb
... ... @@ -454,7 +454,7 @@ module Noosfero::Factory
454 454 end
455 455  
456 456 def defaults_for_suggest_article
457   - { :name => 'Sender', :email => 'sender@example.com', :article_name => 'Some title', :article_body => 'some body text', :article_abstract => 'some abstract text'}
  457 + { :name => 'Sender', :email => 'sender@example.com', :article => {:name => 'Some title', :body => 'some body text', :abstract => 'some abstract text'}}
458 458 end
459 459  
460 460 def defaults_for_comment(params = {})
... ...
test/functional/cms_controller_test.rb
... ... @@ -699,7 +699,7 @@ class CmsControllerTest &lt; ActionController::TestCase
699 699 xhr :get, :update_categories, :profile => profile.identifier, :category_id => top.id
700 700 assert_template 'shared/update_categories'
701 701 assert_equal top, assigns(:current_category)
702   - assert_equal [c1, c2], assigns(:categories)
  702 + assert_equivalent [c1, c2], assigns(:categories)
703 703 end
704 704  
705 705 should 'record when coming from public view on edit' do
... ... @@ -1407,22 +1407,57 @@ class CmsControllerTest &lt; ActionController::TestCase
1407 1407 assert_template 'suggest_an_article'
1408 1408 end
1409 1409  
  1410 + should 'display name and email when a not logged in user suggest an article' do
  1411 + logout
  1412 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1413 +
  1414 + assert_select '#task_name'
  1415 + assert_select '#task_email'
  1416 + end
  1417 +
  1418 + should 'do not display name and email when a logged in user suggest an article' do
  1419 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1420 +
  1421 + assert_select '#task_name', 0
  1422 + assert_select '#task_email', 0
  1423 + end
  1424 +
  1425 + should 'display captcha when suggest an article for not logged in users' do
  1426 + logout
  1427 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1428 +
  1429 + assert_select '#dynamic_recaptcha'
  1430 + end
  1431 +
  1432 + should 'not display captcha when suggest an article for logged in users' do
  1433 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1434 +
  1435 + assert_select '#dynamic_recaptcha', 0
  1436 + end
  1437 +
1410 1438 should 'render TinyMce Editor on suggestion of article' do
1411 1439 logout
1412 1440 get :suggest_an_article, :profile => profile.identifier
1413 1441  
1414   - assert_tag :tag => 'textarea', :attributes => { :name => /article_abstract/, :class => 'mceEditor' }
1415   - assert_tag :tag => 'textarea', :attributes => { :name => /article_body/, :class => 'mceEditor' }
  1442 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[abstract\]/, :class => 'mceEditor' }
  1443 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[body\]/, :class => 'mceEditor' }
1416 1444 end
1417 1445  
1418 1446 should 'create a task suggest task to a profile' do
1419 1447 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1420 1448  
1421 1449 assert_difference 'SuggestArticle.count' do
1422   - post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article_name => 'some name', :article_body => 'some body', :email => 'some@localhost.com', :name => 'some name'}
  1450 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}, :email => 'some@localhost.com', :name => 'some name'}
1423 1451 end
1424 1452 end
1425 1453  
  1454 + should 'create suggest task with logged in user as the article author' do
  1455 + c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
  1456 +
  1457 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}}
  1458 + assert_equal profile, SuggestArticle.last.requestor
  1459 + end
  1460 +
1426 1461 should 'suggest an article from a profile' do
1427 1462 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1428 1463 get :suggest_an_article, :profile => c.identifier, :back_to => c.identifier
... ...
test/functional/content_viewer_controller_test.rb
... ... @@ -780,6 +780,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
780 780 assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/
781 781 end
782 782  
  783 + should 'show only first paragraph with picture of posts if visualization_format is short+pic' do
  784 + login_as(profile.identifier)
  785 +
  786 + blog = Blog.create!(:name => 'A blog test', :profile => profile, :visualization_format => 'short+pic')
  787 +
  788 + blog.posts << TinyMceArticle.create!(:name => 'first post', :parent => blog, :profile => profile, :body => '<p>Content to be displayed.</p> <img src="pic.jpg">')
  789 +
  790 + get :view_page, :profile => profile.identifier, :page => blog.path
  791 +
  792 + assert_select '.blog-post .post-pic' do |el|
  793 + assert_match /background-image:url\(pic.jpg\)/, el.to_s
  794 + end
  795 + end
  796 +
783 797 should 'display link to edit blog for allowed' do
784 798 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
785 799 login_as(profile.identifier)
... ...
test/functional/spam_controller_test.rb
... ... @@ -10,7 +10,7 @@ class SpamControllerTest &lt; ActionController::TestCase
10 10 @article = fast_create(TextileArticle, :profile_id => @community.id)
11 11 @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com')
12 12  
13   - @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article_name => 'Spam article', :email => 'spammer@shady.place', :article_body => "Something you don't need", :target => @community, :spam => true)
  13 + @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article => {:name => 'Spam article', :body => "Something you don't need"}, :email => 'spammer@shady.place', :target => @community, :spam => true)
14 14 login_as @profile.identifier
15 15 end
16 16  
... ...
test/functional/tasks_controller_test.rb
... ... @@ -264,11 +264,11 @@ class TasksControllerTest &lt; ActionController::TestCase
264 264 c = fast_create(Community)
265 265 c.add_admin profile
266 266 @controller.stubs(:profile).returns(c)
267   - t = SuggestArticle.create!(:article_name => 'test name', :article_abstract => 'test abstract', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c)
  267 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
268 268  
269 269 get :index
270   - assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /article_abstract/, :class => 'mceEditor' }
271   - assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /article_body/, :class => 'mceEditor' }
  270 + assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[abstract\]/, :class => 'mceEditor' }
  271 + assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[body\]/, :class => 'mceEditor' }
272 272 end
273 273  
274 274 should 'create TinyMceArticle article after finish approve suggested article task' do
... ... @@ -276,7 +276,7 @@ class TasksControllerTest &lt; ActionController::TestCase
276 276 c = fast_create(Community)
277 277 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
278 278 @controller.stubs(:profile).returns(c)
279   - t = SuggestArticle.create!(:article_name => 'test name', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c)
  279 + t = SuggestArticle.create!(:article => {:name => 'test name', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
280 280  
281 281 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}}
282 282 assert_not_nil TinyMceArticle.find(:first)
... ... @@ -288,16 +288,13 @@ class TasksControllerTest &lt; ActionController::TestCase
288 288 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
289 289 @controller.stubs(:profile).returns(c)
290 290 t = SuggestArticle.new
291   - t.article_name = 'test name'
292   - t.article_body = 'test body'
  291 + t.article = {:name => 'test name', :body => 'test body', :source => 'http://test.com', :source_name => 'some source name'}
293 292 t.name = 'some name'
294   - t.source = 'http://test.com'
295   - t.source_name = 'some source name'
296 293 t.email = 'test@localhost.com'
297 294 t.target = c
298 295 t.save!
299 296  
300   - post :close, :tasks => {t.id => { :task => {:article_name => 'new article name', :article_body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source', :name => 'new name'}, :decision => "finish"}}
  297 + post :close, :tasks => {t.id => { :task => {:article => {:name => 'new article name', :body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source'}, :name => 'new name'}, :decision => "finish"}}
301 298 assert_equal 'new article name', TinyMceArticle.find(:first).name
302 299 assert_equal 'new name', TinyMceArticle.find(:first).author_name
303 300 assert_equal 'new body', TinyMceArticle.find(:first).body
... ... @@ -305,6 +302,28 @@ class TasksControllerTest &lt; ActionController::TestCase
305 302 assert_equal 'new source', TinyMceArticle.find(:first).source_name
306 303 end
307 304  
  305 + should "display name from article suggestion when requestor was not setted" do
  306 + Task.destroy_all
  307 + c = fast_create(Community)
  308 + c.add_admin profile
  309 + @controller.stubs(:profile).returns(c)
  310 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  311 +
  312 + get :index
  313 + assert_select "#tasks_#{t.id}_task_name"
  314 + end
  315 +
  316 + should "not display name from article suggestion when requestor was setted" do
  317 + Task.destroy_all
  318 + c = fast_create(Community)
  319 + c.add_admin profile
  320 + @controller.stubs(:profile).returns(c)
  321 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :requestor => fast_create(Person), :target => c)
  322 +
  323 + get :index
  324 + assert_select "#tasks_#{t.id}_task_name", 0
  325 + end
  326 +
308 327 should "not crash if accessing close without tasks parameter" do
309 328 assert_nothing_raised do
310 329 post :close
... ...
test/unit/article_test.rb
... ... @@ -1715,6 +1715,18 @@ class ArticleTest &lt; ActiveSupport::TestCase
1715 1715 assert_equal 'bar.png', a.first_image
1716 1716 end
1717 1717  
  1718 + should 'get first image from having_image' do
  1719 + a = fast_create(Article,
  1720 + :body => '<p>Foo</p><p><img src="bar.png" /></p>',
  1721 + :abstract => '<p>Lead</p><p><img src="lead.png" /></p>'
  1722 + )
  1723 + img = {}
  1724 + img.expects(:present?).returns true
  1725 + img.expects(:public_filename).returns 'pic.jpg'
  1726 + a.expects(:image).at_least_once.returns img
  1727 + assert_equal 'pic.jpg', a.first_image
  1728 + end
  1729 +
1718 1730 should 'not get first image from anywhere' do
1719 1731 a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>')
1720 1732 assert_equal '', a.first_image
... ...
test/unit/blog_helper_test.rb
... ... @@ -20,30 +20,36 @@ class BlogHelperTest &lt; ActionView::TestCase
20 20 def _(s); s; end
21 21 def h(s); s; end
22 22  
23   - should 'list published posts with class blog-post' do
24   - blog.children << published_post = create(TextileArticle, :name => 'Post', :profile => profile, :parent => blog, :published => true)
25   -
26   - expects(:display_post).with(anything, anything).returns('POST')
27   - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last odd-post-inner', :id => "post-#{published_post.id}").returns('POST')
28   - expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')
29   -
30   - assert_equal 'RESULT', list_posts(blog.posts)
31   - end
32   -
33   - should 'list even/odd posts with a different class' do
34   - blog.children << older_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => blog, :published => true)
35   -
36   - blog.children << newer_post = create(TextileArticle, :name => 'Second post', :profile => profile, :parent => blog, :published => true)
37   -
38   - expects(:display_post).with(anything, anything).returns('POST').times(2)
39   -
40   - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first odd-post-inner', :id => "post-#{newer_post.id}").returns('POST 1')
41   - expects(:content_tag).with('div', "POST 1", :class => 'odd-post').returns('ODD-POST')
42   -
43   - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-2 last even-post-inner', :id => "post-#{older_post.id}").returns('POST 2')
44   - expects(:content_tag).with('div', "POST 2", :class => 'even-post').returns('EVEN-POST')
45   -
46   - assert_equal "ODD-POST\n<hr class='sep-posts'/>\nEVEN-POST", list_posts(blog.posts)
  23 + should 'list blog posts with identifiers and classes' do
  24 + blog.children << older_post = create(TextileArticle, :name => 'First post',
  25 + :profile => profile, :parent => blog, :published => true)
  26 + blog.children << some_post = create(TextileArticle, :name => 'Some post',
  27 + :profile => profile, :parent => blog, :published => true)
  28 + blog.children << hidden_post = create(TextileArticle, :name => 'Hidden post',
  29 + :profile => profile, :parent => blog, :published => false)
  30 + blog.children << newer_post = create(TextileArticle, :name => 'Last post',
  31 + :profile => profile, :parent => blog, :published => true)
  32 +
  33 + def content_tag(tag, content_or_options_with_block = nil, options = nil, &block)
  34 + if block_given?
  35 + options = content_or_options_with_block
  36 + content = block.call
  37 + else
  38 + content = content_or_options_with_block
  39 + end
  40 + options ||= {}
  41 + "<#{tag}#{options.map{|k,v| " #{k}=\"#{[v].flatten.join(' ')}\""}.join}>#{content}</#{tag}>"
  42 + end
  43 +
  44 + html = HTML::Document.new(list_posts(blog.posts)).root
  45 + assert_select html, "div#post-#{newer_post.id}.blog-post.position-1.first.odd-post" +
  46 + " > div.odd-post-inner.blog-post-inner > .title", 'Last post'
  47 + assert_select html, "div#post-#{hidden_post.id}.blog-post.position-2.not-published.even-post" +
  48 + " > div.even-post-inner.blog-post-inner > .title", 'Hidden post'
  49 + assert_select html, "div#post-#{some_post.id}.blog-post.position-3.odd-post" +
  50 + " > div.odd-post-inner.blog-post-inner > .title", 'Some post'
  51 + assert_select html, "div#post-#{older_post.id}.blog-post.position-4.last.even-post" +
  52 + " > div.even-post-inner.blog-post-inner > .title", 'First post'
47 53 end
48 54  
49 55  
... ...
test/unit/boxes_helper_test.rb
... ... @@ -3,6 +3,7 @@ require &#39;boxes_helper&#39;
3 3  
4 4 class BoxesHelperTest < ActionView::TestCase
5 5  
  6 + include ApplicationHelper
6 7 include BoxesHelper
7 8 include ActionView::Helpers::TagHelper
8 9  
... ... @@ -181,4 +182,20 @@ class BoxesHelperTest &lt; ActionView::TestCase
181 182 display_box_content(box, '')
182 183 end
183 184  
  185 + should 'display embed button when a block is embedable' do
  186 + box = create(Box, position: 1, owner: fast_create(Profile))
  187 + block = Block.create!(:box => box)
  188 + block.stubs(:embedable?).returns(true)
  189 + stubs(:url_for).returns('')
  190 + assert_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '}
  191 + end
  192 +
  193 + should 'not display embed button when a block is not embedable' do
  194 + box = create(Box, position: 1, owner: fast_create(Profile))
  195 + block = Block.create!(:box => box)
  196 + block.stubs(:embedable?).returns(false)
  197 + stubs(:url_for).returns('')
  198 + assert_no_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '}
  199 + end
  200 +
184 201 end
... ...
test/unit/suggest_article_test.rb
... ... @@ -13,16 +13,9 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
13 13  
14 14 should 'have the article_name' do
15 15 t = SuggestArticle.new
16   - assert !t.errors[:article_name.to_s].present?
17   - t.valid?
18   - assert t.errors[:article_name.to_s].present?
19   - end
20   -
21   - should 'have the article_body' do
22   - t = SuggestArticle.new
23   - assert !t.errors[:article_body.to_s].present?
24   - t.valid?
25   - assert t.errors[:article_body.to_s].present?
  16 + assert !t.article_object.errors[:name].present?
  17 + t.article_object.valid?
  18 + assert t.article_object.errors[:name].present?
26 19 end
27 20  
28 21 should 'have the email' do
... ... @@ -46,19 +39,12 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
46 39 assert t.errors[:target_id.to_s].present?
47 40 end
48 41  
49   - should 'have the article_abstract' do
  42 + should 'have the article' do
50 43 t = SuggestArticle.new
51   - assert t.respond_to?(:article_abstract)
52   - end
53   -
54   - should 'have the article_parent_id' do
55   - t = SuggestArticle.new
56   - assert t.respond_to?(:article_parent_id)
57   - end
58   -
59   - should 'source be defined' do
60   - t = SuggestArticle.new
61   - assert t.respond_to?(:source)
  44 + assert t.respond_to?(:article_object)
  45 + assert !t.errors[:article_object].present?
  46 + t.valid?
  47 + assert t.errors[:article_object].present?
62 48 end
63 49  
64 50 should 'create an article on with perfom method' do
... ... @@ -66,9 +52,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
66 52 name = 'some name'
67 53 body = 'some body'
68 54 abstract = 'some abstract'
69   - t.article_name = name
70   - t.article_body = body
71   - t.article_abstract = abstract
  55 + t.article = {:name => name, :body => body, :abstract => abstract}
72 56 t.target = @profile
73 57 count = TinyMceArticle.count
74 58 t.perform
... ... @@ -77,8 +61,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
77 61  
78 62 should 'fill source name and URL into created article' do
79 63 t = build(SuggestArticle, :target => @profile)
80   - t.source_name = 'GNU project'
81   - t.source = 'http://www.gnu.org/'
  64 + t.article.merge!({:source_name => 'GNU project', :source => 'http://www.gnu.org/'})
82 65 t.perform
83 66  
84 67 article = TinyMceArticle.last
... ... @@ -95,7 +78,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
95 78  
96 79 should 'highlight created article' do
97 80 t = build(SuggestArticle, :target => @profile)
98   - t.highlighted = true
  81 + t.article[:highlighted] = true
99 82 t.perform
100 83  
101 84 article = TinyMceArticle.last(:conditions => { :name => t.article_name}) # just to be sure
... ... @@ -132,19 +115,19 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
132 115 end
133 116  
134 117 should 'have target notification message' do
135   - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe')
  118 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
136 119  
137 120 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}.*[\n]*.*to approve or reject/, task.target_notification_message)
138 121 end
139 122  
140 123 should 'have target notification description' do
141   - task = build(SuggestArticle,:target => @profile, :article_name => 'suggested article', :name => 'johndoe')
  124 + task = build(SuggestArticle,:target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
142 125  
143 126 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, task.target_notification_description)
144 127 end
145 128  
146 129 should 'deliver target notification message' do
147   - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com')
  130 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
148 131  
149 132 email = TaskMailer.target_notification(task, task.target_notification_message).deliver
150 133  
... ... @@ -160,7 +143,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
160 143 should 'delegate spam detection to plugins' do
161 144 Environment.default.enable_plugin(EverythingIsSpam)
162 145  
163   - t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com')
  146 + t1 = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
164 147  
165 148 EverythingIsSpam.any_instance.expects(:check_for_spam)
166 149  
... ... @@ -189,7 +172,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
189 172 should 'notify plugins of suggest_articles being marked as spam' do
190 173 Environment.default.enable_plugin(SpamNotification)
191 174  
192   - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com')
  175 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
193 176  
194 177 t.spam!
195 178 process_delayed_job_queue
... ... @@ -200,7 +183,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
200 183 should 'notify plugins of suggest_articles being marked as ham' do
201 184 Environment.default.enable_plugin(SpamNotification)
202 185  
203   - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com')
  186 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
204 187  
205 188 t.ham!
206 189 process_delayed_job_queue
... ... @@ -219,10 +202,23 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
219 202 end
220 203  
221 204 should 'log spammer ip after marking comment as spam' do
222   - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com', :ip_address => '192.168.0.1')
  205 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com', :ip_address => '192.168.0.1')
223 206 t.spam!
224 207 log = File.open('log/test_spammers.log')
225 208 assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read
226 209 end
227 210  
  211 + should 'not require name and email when requestor is present' do
  212 + t = SuggestArticle.new(:requestor => fast_create(Person))
  213 + t.valid?
  214 + assert t.errors[:email].blank?
  215 + assert t.errors[:name].blank?
  216 + end
  217 +
  218 + should 'return name as sender when requestor is setted' do
  219 + person = fast_create(Person)
  220 + t = SuggestArticle.new(:requestor => person)
  221 + assert_equal person.name, t.sender
  222 + end
  223 +
228 224 end
... ...
test/unit/user_test.rb
... ... @@ -87,6 +87,14 @@ class UserTest &lt; ActiveSupport::TestCase
87 87 assert_equal person_count + 1, Person.count
88 88 end
89 89  
  90 + def test_should_create_person_with_identifier_different_from_login
  91 + user = User.create!(:login => 'new_user', :email => 'new_user@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:identifier => "new_test"})
  92 +
  93 + assert Person.exists?(['user_id = ?', user.id])
  94 +
  95 + assert user.login != user.person.identifier
  96 + end
  97 +
90 98 def test_login_validation
91 99 u = User.new
92 100 u.valid?
... ... @@ -355,7 +363,7 @@ class UserTest &lt; ActiveSupport::TestCase
355 363 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010'))
356 364 expected_hash = {
357 365 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8,
358   - 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil,
  366 + 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil,
359 367 'amount_of_friends' => 0, 'friends_list' => {}, 'enterprises' => [],
360 368 }
361 369  
... ...