Commit 84bbcd40d2aa4e5fc1842107c55763afdbe32cc3

Authored by Victor Costa
1 parent 4e32d3ef

rails3: fix unit tests

Showing 50 changed files with 965 additions and 263 deletions   Show diff stats
app/mailers/comment_notifier.rb
... ... @@ -13,7 +13,7 @@ class Comment::Notifier < ActionMailer::Base
13 13  
14 14 mail(
15 15 to: comment.notification_emails,
16   - from: "#{profile.environment.name} <#{profile.environment.contact_email}>",
  16 + from: "#{profile.environment.name} <#{profile.environment.noreply_email}>",
17 17 subject: _("[%s] you got a new comment!") % [profile.environment.name]
18 18 )
19 19 end
... ... @@ -33,7 +33,7 @@ class Comment::Notifier &lt; ActionMailer::Base
33 33  
34 34 mail(
35 35 bcc: emails,
36   - from: "#{profile.environment.name} <#{profile.environment.contact_email}>",
  36 + from: "#{profile.environment.name} <#{profile.environment.noreply_email}>",
37 37 subject: _("[%s] %s commented on a content of %s") % [profile.environment.name, comment.author_name, profile.short_name]
38 38 )
39 39 end
... ...
app/mailers/scrap_notifier.rb
... ... @@ -10,7 +10,7 @@ class Scrap::Notifier &lt; ActionMailer::Base
10 10 @url = sender.environment.top_url
11 11 mail(
12 12 to: receiver.email,
13   - from: "#{sender.environment.name} <#{sender.environment.contact_email}>",
  13 + from: "#{sender.environment.name} <#{sender.environment.noreply_email}>",
14 14 subject: _("[%s] You received a scrap!") % [sender.environment.name]
15 15 )
16 16 end
... ...
app/models/comment.rb
... ... @@ -170,40 +170,6 @@ class Comment &lt; ActiveRecord::Base
170 170 body || ''
171 171 end
172 172  
173   - class Notifier < ActionMailer::Base
174   - def mail(comment)
175   - profile = comment.article.profile
176   - recipients comment.notification_emails
177   - from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
178   - subject _("[%s] you got a new comment!") % [profile.environment.name]
179   - body :recipient => profile.nickname || profile.name,
180   - :sender => comment.author_name,
181   - :sender_link => comment.author_link,
182   - :article_title => comment.article.name,
183   - :comment_url => comment.url,
184   - :comment_title => comment.title,
185   - :comment_body => comment.body,
186   - :environment => profile.environment.name,
187   - :url => profile.environment.top_url
188   - end
189   - def mail_to_followers(comment, emails)
190   - profile = comment.article.profile
191   - bcc emails
192   - from "#{profile.environment.name} <#{profile.environment.noreply_email}>"
193   - subject _("[%s] %s commented on a content of %s") % [profile.environment.name, comment.author_name, profile.short_name]
194   - body :recipient => profile.nickname || profile.name,
195   - :sender => comment.author_name,
196   - :sender_link => comment.author_link,
197   - :article_title => comment.article.name,
198   - :comment_url => comment.url,
199   - :unsubscribe_url => comment.article.view_url.merge({:unfollow => true}),
200   - :comment_title => comment.title,
201   - :comment_body => comment.body,
202   - :environment => profile.environment.name,
203   - :url => profile.environment.top_url
204   - end
205   - end
206   -
207 173 def rejected?
208 174 @rejected
209 175 end
... ...
app/models/friendship.rb
... ... @@ -7,12 +7,12 @@ class Friendship &lt; ActiveRecord::Base
7 7 belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
8 8  
9 9 after_create do |friendship|
10   - update_cache_counter(:friends_count, friendship.person, 1)
11   - update_cache_counter(:friends_count, friendship.friend, 1)
  10 + Friendship.update_cache_counter(:friends_count, friendship.person, 1)
  11 + Friendship.update_cache_counter(:friends_count, friendship.friend, 1)
12 12 end
13 13  
14 14 after_destroy do |friendship|
15   - update_cache_counter(:friends_count, friendship.person, -1)
16   - update_cache_counter(:friends_count, friendship.friend, -1)
  15 + Friendship.update_cache_counter(:friends_count, friendship.person, -1)
  16 + Friendship.update_cache_counter(:friends_count, friendship.friend, -1)
17 17 end
18 18 end
... ...
app/models/person_notifier.rb
... ... @@ -13,7 +13,7 @@ class PersonNotifier
13 13 end
14 14  
15 15 def dispatch_notification_mail
16   - Delayed::Job.enqueue(NotifyJob.new(@person.id), nil, @person.notification_time.hours.from_now) if @person.notification_time>0
  16 + Delayed::Job.enqueue(NotifyJob.new(@person.id), {:run_at => @person.notification_time.hours.from_now}) if @person.notification_time>0
17 17 end
18 18  
19 19 def reschedule_next_notification_mail
... ... @@ -27,7 +27,7 @@ class PersonNotifier
27 27 from = @person.last_notification || DateTime.now - @person.notification_time.hours
28 28 notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from])
29 29 Noosfero.with_locale @person.environment.default_language do
30   - Mailer::deliver_content_summary(@person, notifications) unless notifications.empty?
  30 + Mailer::content_summary(@person, notifications).deliver unless notifications.empty?
31 31 end
32 32 @person.settings[:last_notification] = DateTime.now
33 33 @person.save!
... ... @@ -36,7 +36,7 @@ class PersonNotifier
36 36  
37 37 class NotifyAllJob
38 38 def self.exists?
39   - Delayed::Job.where(:handler => "--- !ruby/object:PersonNotifier::NotifyAllJob {}\n\n").count > 0
  39 + Delayed::Job.where(:handler => "--- !ruby/object:PersonNotifier::NotifyAllJob {}\n").count > 0
40 40 end
41 41  
42 42 def perform
... ... @@ -51,14 +51,14 @@ class PersonNotifier
51 51 end
52 52  
53 53 def self.find(person_id)
54   - Delayed::Job.where(:handler => "--- !ruby/struct:PersonNotifier::NotifyJob \nperson_id: #{person_id}\n")
  54 + Delayed::Job.where(:handler => "--- !ruby/struct:PersonNotifier::NotifyJob\nperson_id: #{person_id}\n")
55 55 end
56 56  
57 57 def perform
58 58 Person.find(person_id).notifier.notify
59 59 end
60 60  
61   - def on_permanent_failure
  61 + def failure(job)
62 62 person = Person.find(person_id)
63 63 person.notifier.dispatch_notification_mail
64 64 end
... ... @@ -76,14 +76,16 @@ class PersonNotifier
76 76 def content_summary(person, notifications)
77 77 @current_theme = 'default'
78 78 @profile = person
79   - recipients person.email
80   - from "#{@profile.environment.name} <#{@profile.environment.contact_email}>"
81   - subject _("[%s] Network Activity") % [@profile.environment.name]
82   - body :recipient => @profile.nickname || @profile.name,
83   - :environment => @profile.environment.name,
84   - :url => @profile.environment.top_url,
85   - :notifications => notifications
86   - content_type "text/html"
  79 + @recipient = @profile.nickname || @profile.name
  80 + @notifications = notifications
  81 + @environment = @profile.environment.name
  82 + @url = @profile.environment.top_url
  83 + mail(
  84 + content_type: "text/html",
  85 + from: "#{@profile.environment.name} <#{@profile.environment.contact_email}>",
  86 + to: @profile.email,
  87 + subject: _("[%s] Network Activity") % [@profile.environment.name]
  88 + )
87 89 end
88 90 end
89 91 end
... ...
app/models/scrap.rb
... ... @@ -57,21 +57,4 @@ class Scrap &lt; ActiveRecord::Base
57 57 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
58 58 end
59 59  
60   - class Notifier < ActionMailer::Base
61   - def mail(scrap)
62   - sender, receiver = scrap.sender, scrap.receiver
63   - recipients receiver.email
64   -
65   - from "#{sender.environment.name} <#{sender.environment.noreply_email}>"
66   - subject _("[%s] You received a scrap!") % [sender.environment.name]
67   - body :recipient => receiver.name,
68   - :sender => sender.name,
69   - :sender_link => sender.url,
70   - :scrap_content => scrap.content,
71   - :wall_url => scrap.scrap_wall_url,
72   - :environment => sender.environment.name,
73   - :url => sender.environment.top_url
74   - end
75   - end
76   -
77 60 end
... ...
app/views/person_notifier/mailer/_add_member_in_community.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_add_member_in_community.rhtml
... ... @@ -1 +0,0 @@
1   -<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_comment.html.erb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +<% Comment %>
  2 +<% Profile %>
  3 +<% Person %>
  4 +
  5 +<table style="background: #f0f0f1;border-bottom: 1px solid #d2d2d2 !important;border-top: 1px solid #fff;margin-bottom: 0;">
  6 +<tr>
  7 + <td>
  8 + <% if comment.author %>
  9 + <%= link_to profile_image(comment.author, :minor),
  10 + comment.author_url,
  11 + :class => 'comment-picture',
  12 + :title => comment.author_name
  13 + %>
  14 + <% end %>
  15 + </td>
  16 + <td>
  17 + <%= comment.author.present? ? link_to(comment.author_name, comment.author.url, :style => "font-size: 12px; color: #333; font-weight: bold; text-decoration: none;") : content_tag('strong', comment.author_name) %>
  18 + <% unless comment.title.blank? %>
  19 + <span style="font-size: 12px;"><%= comment.title %></span><br/>
  20 + <% end %>
  21 + <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
  22 + <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span>
  23 + <br style="clear: both;" />
  24 +
  25 + <% unless comment.replies.blank? %>
  26 + <ul class="comment-replies">
  27 + <% comment.replies.each do |reply| %>
  28 + <%= render :partial => 'comment', :locals => { :comment => reply } %>
  29 + <% end %>
  30 + </ul>
  31 + <% end %>
  32 + </td>
  33 +</table>
... ...
app/views/person_notifier/mailer/_comment.rhtml
... ... @@ -1,33 +0,0 @@
1   -<% Comment %>
2   -<% Profile %>
3   -<% Person %>
4   -
5   -<table style="background: #f0f0f1;border-bottom: 1px solid #d2d2d2 !important;border-top: 1px solid #fff;margin-bottom: 0;">
6   -<tr>
7   - <td>
8   - <% if comment.author %>
9   - <%= link_to profile_image(comment.author, :minor),
10   - comment.author_url,
11   - :class => 'comment-picture',
12   - :title => comment.author_name
13   - %>
14   - <% end %>
15   - </td>
16   - <td>
17   - <%= comment.author.present? ? link_to(comment.author_name, comment.author.url, :style => "font-size: 12px; color: #333; font-weight: bold; text-decoration: none;") : content_tag('strong', comment.author_name) %>
18   - <% unless comment.title.blank? %>
19   - <span style="font-size: 12px;"><%= comment.title %></span><br/>
20   - <% end %>
21   - <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
22   - <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span>
23   - <br style="clear: both;" />
24   -
25   - <% unless comment.replies.blank? %>
26   - <ul class="comment-replies">
27   - <% comment.replies.each do |reply| %>
28   - <%= render :partial => 'comment', :locals => { :comment => reply } %>
29   - <% end %>
30   - </ul>
31   - <% end %>
32   - </td>
33   -</table>
app/views/person_notifier/mailer/_create_article.html.erb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
  9 + <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
  10 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  11 + </p>
  12 + <p>
  13 + <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
  14 + <br/>
  15 + <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
  16 + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') unless activity.params['lead'].blank? %>
  17 + </p>
  18 + <p><%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %></p>
  19 + </td>
  20 +</tr>
  21 +<tr>
  22 + <td></td>
  23 + <td>
  24 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  25 + </td>
  26 +</tr>
  27 +</table>
... ...
app/views/person_notifier/mailer/_create_article.rhtml
... ... @@ -1,27 +0,0 @@
1   -<table>
2   -<tr>
3   - <td>
4   - <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5   - </td>
6   - <td>
7   - <p style="width:550px">
8   - <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
9   - <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
10   - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
11   - </p>
12   - <p>
13   - <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
14   - <br/>
15   - <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span>
16   - <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %>
17   - </p>
18   - <p><%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %></p>
19   - </td>
20   -</tr>
21   -<tr>
22   - <td></td>
23   - <td>
24   - <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
25   - </td>
26   -</tr>
27   -</table>
app/views/person_notifier/mailer/_default_activity.html.erb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +<table>
  2 +<tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +<tr>
  14 + <td></td>
  15 + <td>
  16 + <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
  17 + </td>
  18 +</tr>
  19 +</table>
... ...
app/views/person_notifier/mailer/_default_activity.rhtml
... ... @@ -1,19 +0,0 @@
1   -<table>
2   -<tr>
3   - <td>
4   - <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5   - </td>
6   - <td>
7   - <p style="width:550px">
8   - <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9   - <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10   - </p>
11   - </td>
12   -</tr>
13   -<tr>
14   - <td></td>
15   - <td>
16   - <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
17   - </td>
18   -</tr>
19   -</table>
app/views/person_notifier/mailer/_join_community.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_join_community.rhtml
... ... @@ -1 +0,0 @@
1   -<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_leave_scrap.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_leave_scrap.rhtml
... ... @@ -1 +0,0 @@
1   -<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_leave_scrap_to_self.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_leave_scrap.html.erb
0 2 \ No newline at end of file
... ...
app/views/person_notifier/mailer/_leave_scrap_to_self.rhtml
... ... @@ -1 +0,0 @@
1   -_leave_scrap.rhtml
2 0 \ No newline at end of file
app/views/person_notifier/mailer/_new_friendship.html.erb 0 → 100644
... ... @@ -0,0 +1 @@
  1 +<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
... ...
app/views/person_notifier/mailer/_new_friendship.rhtml
... ... @@ -1 +0,0 @@
1   -<%= render :partial => 'default_activity', :locals => { :activity => activity } %>
app/views/person_notifier/mailer/_profile_comments.html.erb 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +<% if activity.comments_count > 2 %>
  2 + <div style="font-size: 10px;">
  3 + <% if activity.params['url'].blank? %>
  4 + <%= _("%s comments") % activity.comments_count %>
  5 + <% else %>
  6 + <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %>
  7 + <% end %>
  8 + </div>
  9 +<% else %>
  10 + <ul>
  11 + <%= render :partial => 'comment', :collection => activity.comments %>
  12 + </ul>
  13 +<% end %>
... ...
app/views/person_notifier/mailer/_profile_comments.rhtml
... ... @@ -1,13 +0,0 @@
1   -<% if activity.comments_count > 2 %>
2   - <div style="font-size: 10px;">
3   - <% if activity.params['url'].blank? %>
4   - <%= _("%s comments") % activity.comments_count %>
5   - <% else %>
6   - <%= link_to(_("View all %s comments") % activity.comments_count, activity.params['url']) %>
7   - <% end %>
8   - </div>
9   -<% else %>
10   - <ul>
11   - <%= render :partial => 'comment', :collection => activity.comments %>
12   - </ul>
13   -<% end %>
app/views/person_notifier/mailer/_reply_scrap_on_self.html.erb 0 → 120000
... ... @@ -0,0 +1 @@
  1 +_leave_scrap.html.erb
0 2 \ No newline at end of file
... ...
app/views/person_notifier/mailer/_reply_scrap_on_self.rhtml
... ... @@ -1 +0,0 @@
1   -_leave_scrap.rhtml
2 0 \ No newline at end of file
app/views/person_notifier/mailer/_upload_image.html.erb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +<table>
  2 + <tr>
  3 + <td>
  4 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  5 + </td>
  6 + <td>
  7 + <p style="width:550px">
  8 + <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
  9 + <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
  10 + </p>
  11 + </td>
  12 +</tr>
  13 +</table>
  14 +<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
  15 +<br/>
... ...
app/views/person_notifier/mailer/_upload_image.rhtml
... ... @@ -1,15 +0,0 @@
1   -<table>
2   - <tr>
3   - <td>
4   - <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5   - </td>
6   - <td>
7   - <p style="width:550px">
8   - <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9   - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10   - </p>
11   - </td>
12   -</tr>
13   -</table>
14   -<div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
15   -<br/>
app/views/person_notifier/mailer/content_summary.html.erb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +<h3><%= _("%s's network activity") % @profile.name %></h3>
  2 +<br/>
  3 +<div>
  4 +<% @notifications.each do |activity| %>
  5 + <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">
  6 + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
  7 + </div>
  8 +<% end %>
  9 +</div>
  10 +
  11 +<div style="color:#444444;font-size:11px;">
  12 +<p><%= _("Greetings,") %></p>
  13 +<br/>
  14 +<p>--</p>
  15 +<p><%= _('%s team.') % @environment %></p>
  16 +<p><%= url_for @url %></p>
  17 +</div>
  18 +<br/>
... ...
app/views/person_notifier/mailer/content_summary.rhtml
... ... @@ -1,18 +0,0 @@
1   -<h3><%= _("%s's network activity") % @profile.name %></h3>
2   -<br/>
3   -<div>
4   -<% @notifications.each do |activity| %>
5   - <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">
6   - <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
7   - </div>
8   -<% end %>
9   -</div>
10   -
11   -<div style="color:#444444;font-size:11px;">
12   -<p><%= _("Greetings,") %></p>
13   -<br/>
14   -<p>--</p>
15   -<p><%= _('%s team.') % @environment %></p>
16   -<p><%= url_for @url %></p>
17   -</div>
18   -<br/>
lib/activities_counter_cache_job.rb
... ... @@ -6,6 +6,6 @@ class ActivitiesCounterCacheJob
6 6 activities_counts.each do |count|
7 7 ActiveRecord::Base.connection.execute("UPDATE profiles SET activities_count=#{count['count'].to_i} WHERE profiles.id=#{count['id']};")
8 8 end
9   - Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, -3, 1.day.from_now)
  9 + Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3, :run_at => 1.day.from_now})
10 10 end
11 11 end
... ...
lib/feed_handler.rb.orig 0 → 100644
... ... @@ -0,0 +1,110 @@
  1 +require 'feedparser'
  2 +require 'open-uri'
  3 +
  4 +# This class is responsible for processing feeds and pass the items to the
  5 +# respective container.
  6 +#
  7 +# The <tt>max_errors</tt> attribute controls how many times it will retry in
  8 +# case of failure. If a feed fails for <tt>max_errors+1</tt> times, it will be
  9 +# disabled and the last error message will be recorder in the container.
  10 +# The default value is *6*, if you need to change it you can do that in your
  11 +# config/local.rb file like this:
  12 +#
  13 +# FeedHandler.max_errors = 10
  14 +#
  15 +# For the update interval, see FeedUpdater.
  16 +class FeedHandler
  17 +
  18 + # The maximum number
  19 + cattr_accessor :max_errors
  20 + cattr_accessor :disabled_period
  21 +
  22 + self.max_errors = 6
  23 + self.disabled_period = 1.week
  24 +
  25 + def parse(content)
  26 + raise FeedHandler::ParseError, "Content is nil" if content.nil?
  27 + begin
  28 + return FeedParser::Feed::new(content)
  29 + rescue Exception => ex
  30 + raise FeedHandler::ParseError, "Invalid feed format."
  31 + end
  32 + end
  33 +
  34 + def fetch(address)
  35 + begin
  36 + content = ""
  37 + block = lambda { |s| content = s.read }
  38 + content =
  39 + if Rails.env == 'test' && File.exists?(address)
  40 + File.read(address)
  41 + else
  42 + if !valid_url?(address)
  43 + raise InvalidUrl.new("\"%s\" is not a valid URL" % address)
  44 + end
  45 + open(address, "User-Agent" => "Noosfero/#{Noosfero::VERSION}", &block)
  46 + end
  47 + return content
  48 + rescue Exception => ex
  49 + raise FeedHandler::FetchError, ex.message
  50 + end
  51 + end
  52 +
  53 + def process(container)
  54 +<<<<<<< HEAD
  55 + Rails.logger.info("Processing %s with id = %d" % [container.class.name, container.id])
  56 +=======
  57 +>>>>>>> rails235
  58 + begin
  59 + container.class.transaction do
  60 + if container.update_errors > FeedHandler.max_errors && container.fetched_at < (Time.now - FeedHandler.disabled_period)
  61 + container.enabled = true
  62 + container.update_errors = 0
  63 + container.save
  64 + end
  65 + next unless container.enabled
  66 + actually_process_container(container)
  67 + container.update_errors = 0
  68 + container.finish_fetch
  69 + end
  70 + rescue Exception => exception
  71 + Rails.logger.warn("Unknown error from %s ID %d\n%s" % [container.class.name, container.id, exception.to_s])
  72 + Rails.logger.warn("Backtrace:\n%s" % exception.backtrace.join("\n"))
  73 + container.reload
  74 + container.update_errors += 1
  75 + container.error_message = exception.to_s
  76 + if container.update_errors > FeedHandler.max_errors
  77 + container.fetched_at = Time.now
  78 + container.enabled = false
  79 + end
  80 + begin
  81 + container.finish_fetch
  82 + rescue Exception => finish_fetch_exception
  83 + Rails.logger.warn("Unable to finish fetch from %s ID %d\n%s" % [container.class.name, container.id, finish_fetch_exception.to_s])
  84 + Rails.logger.warn("Backtrace:\n%s" % finish_fetch_exception.backtrace.join("\n"))
  85 + end
  86 + end
  87 + end
  88 +
  89 + class InvalidUrl < Exception; end
  90 + class ParseError < Exception; end
  91 + class FetchError < Exception; end
  92 +
  93 + protected
  94 +
  95 + def actually_process_container(container)
  96 + container.clear
  97 + content = fetch(container.address)
  98 + container.fetched_at = Time.now
  99 + parsed_feed = parse(content)
  100 + container.feed_title = parsed_feed.title
  101 + parsed_feed.items[0..container.limit-1].reverse.each do |item|
  102 + container.add_item(item.title, item.link, item.date, item.content)
  103 + end
  104 + end
  105 +
  106 + def valid_url?(url)
  107 + url =~ URI.regexp('http') || url =~ URI.regexp('https')
  108 + end
  109 +
  110 +end
... ...
lib/noosfero/action_tracker_ext.rb
... ... @@ -3,17 +3,17 @@ Rails.configuration.to_prepare do
3 3 extend CacheCounterHelper
4 4  
5 5 after_create do |record|
6   - update_cache_counter(:activities_count, record.user, 1)
  6 + ActionTracker::Record.update_cache_counter(:activities_count, record.user, 1)
7 7 if record.target.kind_of?(Organization)
8   - update_cache_counter(:activities_count, record.target, 1)
  8 + ActionTracker::Record.update_cache_counter(:activities_count, record.target, 1)
9 9 end
10 10 end
11 11  
12 12 after_destroy do |record|
13 13 if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
14   - update_cache_counter(:activities_count, record.user, -1)
  14 + ActionTracker::Record.update_cache_counter(:activities_count, record.user, -1)
15 15 if record.target.kind_of?(Organization)
16   - update_cache_counter(:activities_count, record.target, -1)
  16 + ActionTracker::Record.update_cache_counter(:activities_count, record.target, -1)
17 17 end
18 18 end
19 19 end
... ...
lib/noosfero/plugin.rb.orig 0 → 100644
... ... @@ -0,0 +1,639 @@
  1 +require 'noosfero'
  2 +
  3 +class Noosfero::Plugin
  4 +
  5 + attr_accessor :context
  6 +
  7 + def initialize(context=nil)
  8 + self.context = context
  9 + end
  10 +
  11 + class << self
  12 +
  13 + attr_writer :should_load
  14 +
  15 + def should_load
  16 + @should_load.nil? && true || @boot
  17 + end
  18 +
  19 +<<<<<<< HEAD
  20 + def initialize!
  21 + return if !should_load
  22 + enabled.each do |plugin_dir|
  23 + plugin_name = File.basename(plugin_dir)
  24 + plugin = load_plugin(plugin_name)
  25 + load_plugin_extensions(plugin_dir)
  26 + load_plugin_filters(plugin)
  27 + end
  28 + end
  29 +
  30 + def setup(config)
  31 + return if !should_load
  32 + enabled.each do |dir|
  33 + setup_plugin(dir, config)
  34 +=======
  35 + def init_system
  36 + available_plugins.each do |dir|
  37 + load_plugin dir
  38 +>>>>>>> rails235
  39 + end
  40 + end
  41 +
  42 + def setup_plugin(dir, config)
  43 + plugin_name = File.basename(dir)
  44 +
  45 + plugin_dependencies_ok = true
  46 + plugin_dependencies_file = File.join(dir, 'dependencies.rb')
  47 + if File.exists?(plugin_dependencies_file)
  48 + begin
  49 + require plugin_dependencies_file
  50 + rescue LoadError => ex
  51 + plugin_dependencies_ok = false
  52 + $stderr.puts "W: Noosfero plugin #{plugin_name} failed to load (#{ex})"
  53 + end
  54 + end
  55 +
  56 + if plugin_dependencies_ok
  57 + %w[
  58 + controllers
  59 + controllers/public
  60 + controllers/profile
  61 + controllers/myprofile
  62 + controllers/admin
  63 + ].each do |folder|
  64 + config.autoload_paths << File.join(dir, folder)
  65 + end
  66 + [ config.autoload_paths, $:].each do |path|
  67 + path << File.join(dir, 'models')
  68 + path << File.join(dir, 'lib')
  69 + # load vendor/plugins
  70 + Dir.glob(File.join(dir, '/vendor/plugins/*')).each do |vendor_plugin|
  71 + path << "#{vendor_plugin}/lib"
  72 + init = "#{vendor_plugin}/init.rb"
  73 + require init.gsub(/.rb$/, '') if File.file? init
  74 + end
  75 + end
  76 +
  77 + # add view path
  78 + ActionController::Base.view_paths.unshift(File.join(dir, 'views'))
  79 + end
  80 + end
  81 +
  82 + def load_plugin(plugin_name)
  83 + (plugin_name.to_s.camelize + 'Plugin').constantize
  84 + end
  85 +
  86 + # This is a generic method that initialize any possible filter defined by a
  87 + # plugin to a specific controller
  88 + def load_plugin_filters(plugin)
  89 + plugin_methods = plugin.instance_methods.select {|m| m.to_s.end_with?('_filters')}
  90 + plugin_methods.each do |plugin_method|
  91 + controller_class = plugin_method.to_s.gsub('_filters', '').camelize.constantize
  92 + filters = plugin.new.send(plugin_method)
  93 + filters = [filters] if !filters.kind_of?(Array)
  94 +
  95 + filters.each do |plugin_filter|
  96 + filter_method = (plugin.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]).to_sym
  97 + controller_class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {}))
  98 + controller_class.send(:define_method, filter_method) do
  99 + instance_eval(&plugin_filter[:block]) if environment.plugin_enabled?(plugin)
  100 + end
  101 + end
  102 + end
  103 + end
  104 +
  105 + def load_plugin_extensions(dir)
  106 + Rails.configuration.to_prepare do
  107 + Dir[File.join(dir, 'lib', 'ext', '*.rb')].each {|file| require_dependency file }
  108 + end
  109 + end
  110 +
  111 + def enabled
  112 + @enabled ||=
  113 + begin
  114 + plugins = Dir.glob(Rails.root.join('config', 'plugins', '*'))
  115 + if Rails.env.test? && !plugins.include?(Rails.root.join('config', 'plugins', 'foo'))
  116 + plugins << Rails.root.join('plugins', 'foo')
  117 + end
  118 + plugins.select do |entry|
  119 + File.directory?(entry)
  120 + end
  121 + end
  122 + end
  123 +
  124 +<<<<<<< HEAD
  125 +
  126 + def all
  127 + @all ||= []
  128 +=======
  129 + def available_plugins
  130 + unless @available_plugins
  131 + path = File.join(Rails.root, 'config', 'plugins', '*')
  132 + @available_plugins = Dir.glob(path).select{ |i| File.directory?(i) }
  133 + if Rails.env.test? && !@available_plugins.include?(File.join(Rails.root, 'config', 'plugins', 'foo'))
  134 + @available_plugins << File.join(Rails.root, 'plugins', 'foo')
  135 + end
  136 + end
  137 + @available_plugins
  138 +>>>>>>> rails235
  139 + end
  140 +
  141 + def all
  142 + @all ||= available_plugins.map{ |dir| (File.basename(dir) + "_plugin").camelize }
  143 + end
  144 +
  145 + def public_name
  146 + self.name.underscore.gsub('_plugin','')
  147 + end
  148 +
  149 + def public_path(file = '')
  150 + File.join('/plugins', public_name, file)
  151 + end
  152 +
  153 + def root_path
  154 + Rails.root.join('plugins', public_name)
  155 + end
  156 +
  157 + def view_path
  158 + File.join(root_path,'views')
  159 + end
  160 +
  161 + # Here the developer should specify the meta-informations that the plugin can
  162 + # inform.
  163 + def plugin_name
  164 + self.name.underscore.humanize
  165 + end
  166 + def plugin_description
  167 + _("No description informed.")
  168 + end
  169 +
  170 + def admin_url
  171 + {:controller => "#{name.underscore}_admin", :action => 'index'}
  172 + end
  173 +
  174 + def has_admin_url?
  175 + File.exists?(File.join(root_path, 'controllers', "#{name.underscore}_admin_controller.rb"))
  176 + end
  177 + end
  178 +
  179 + def expanded_template(file_path, locals = {})
  180 + views_path = Rails.root.join('plugins', "#{self.class.public_name}", 'views')
  181 + ERB.new(File.read("#{views_path}/#{file_path}")).result(binding)
  182 + end
  183 +
  184 + def extra_blocks(params = {})
  185 + return [] if self.class.extra_blocks.nil?
  186 + blocks = self.class.extra_blocks.map do |block, options|
  187 + type = options[:type]
  188 + type = type.is_a?(Array) ? type : [type].compact
  189 + type = type.map do |x|
  190 + x.is_a?(String) ? x.capitalize.constantize : x
  191 + end
  192 + raise "This is not a valid type" if !type.empty? && ![Person, Community, Enterprise, Environment].detect{|m| type.include?(m)}
  193 +
  194 + position = options[:position]
  195 + position = position.is_a?(Array) ? position : [position].compact
  196 + position = position.map{|p| p.to_i}
  197 + raise "This is not a valid position" if !position.empty? && ![1,2,3].detect{|m| position.include?(m)}
  198 +
  199 + if !type.empty? && (params[:type] != :all)
  200 + block = type.include?(params[:type]) ? block : nil
  201 + end
  202 +
  203 + if !position.empty? && !params[:position].nil?
  204 + block = position.detect{ |p| [params[:position]].flatten.include?(p)} ? block : nil
  205 + end
  206 +
  207 + block
  208 + end
  209 + blocks.compact!
  210 + blocks || []
  211 + end
  212 +
  213 + def macros
  214 + self.class.constants.map do |constant_name|
  215 + self.class.const_get(constant_name)
  216 + end.select {|const| const.is_a?(Class) && const < Noosfero::Plugin::Macro}
  217 + end
  218 +
  219 + # Here the developer may specify the events to which the plugins can
  220 + # register and must return true or false. The default value must be false.
  221 + # Must also explicitly define its returning variables.
  222 +
  223 + # -> If true, noosfero will include plugin_dir/public/style.css into
  224 + # application
  225 + def stylesheet?
  226 + false
  227 + end
  228 +
  229 + # -> Adds buttons to the control panel
  230 + # returns = { :title => title, :icon => icon, :url => url }
  231 + # title = name that will be displayed.
  232 + # icon = css class name (for customized icons include them in a css file).
  233 + # url = url or route to which the button will redirect.
  234 + def control_panel_buttons
  235 + nil
  236 + end
  237 +
  238 + # -> Customize profile block design and behavior
  239 + # (overwrites profile_image_link function)
  240 + # returns = lambda block that creates html code.
  241 + def profile_image_link(profile, size, tag, extra_info)
  242 + nil
  243 + end
  244 +
  245 + # -> Adds tabs to the profile
  246 + # returns = { :title => title, :id => id, :content => content, :start => start }
  247 + # title = name that will be displayed.
  248 + # id = div id.
  249 + # content = lambda block that creates html code.
  250 + # start = boolean that specifies if the tab must come before noosfero tabs (optional).
  251 + def profile_tabs
  252 + nil
  253 + end
  254 +
  255 + # -> Adds plugin-specific content types to CMS
  256 + # returns = [ContentClass1, ContentClass2, ...]
  257 + def content_types
  258 + nil
  259 + end
  260 +
  261 + # -> Adds content to calalog item
  262 + # returns = lambda block that creates html code
  263 + def catalog_item_extras(item)
  264 + nil
  265 + end
  266 +
  267 + # -> Adds content to profile editor info and settings
  268 + # returns = lambda block that creates html code or raw rhtml/html.erb
  269 + def profile_editor_extras
  270 + nil
  271 + end
  272 +
  273 + # -> Adds content to calalog list item
  274 + # returns = lambda block that creates html code
  275 + def catalog_list_item_extras(item)
  276 + nil
  277 + end
  278 +
  279 + # -> Adds content to products info
  280 + # returns = lambda block that creates html code
  281 + def product_info_extras(product)
  282 + nil
  283 + end
  284 +
  285 + # -> Adds content to products on asset list
  286 + # returns = lambda block that creates html code
  287 + def asset_product_extras(product)
  288 + nil
  289 + end
  290 +
  291 + # -> Adds a property to the product on asset products
  292 + # returns = {:name => name, :content => content}
  293 + # name = Name of the property
  294 + # content = lambda block that creates an html
  295 + def asset_product_properties(product)
  296 + nil
  297 + end
  298 +
  299 + # -> Adds content to the beginning of the page
  300 + # returns = lambda block that creates html code or raw rhtml/html.erb
  301 + def body_beginning
  302 + nil
  303 + end
  304 +
  305 + # -> Adds content to the ending of the page head
  306 + # returns = lambda block that creates html code or raw rhtml/html.erb
  307 + def head_ending
  308 + nil
  309 + end
  310 +
  311 + # -> Adds plugins' javascript files to application
  312 + # returns = ['example1.js', 'javascripts/example2.js', 'example3.js']
  313 + def js_files
  314 + []
  315 + end
  316 +
  317 + # -> Adds stuff in user data hash
  318 + # returns = { :some_data => some_value, :another_data => another_value }
  319 + def user_data_extras
  320 + {}
  321 + end
  322 +
  323 + # -> Parse and possibly make changes of content (article, block, etc) during HTML rendering
  324 + # returns = content as string after parser and changes
  325 + def parse_content(html, source)
  326 + [html, source]
  327 + end
  328 +
  329 + # -> Adds links to the admin panel
  330 + # returns = {:title => title, :url => url}
  331 + # title = name that will be displayed in the link
  332 + # url = url or route to which the link will redirect to.
  333 + def admin_panel_links
  334 + nil
  335 + end
  336 +
  337 + # -> Adds buttons to manage members page
  338 + # returns = { :title => title, :icon => icon, :url => url }
  339 + # title = name that will be displayed.
  340 + # icon = css class name (for customized icons include them in a css file).
  341 + # url = url or route to which the button will redirect.
  342 + def manage_members_extra_buttons
  343 + nil
  344 + end
  345 +
  346 + # This method will be called just before a comment is saved to the database.
  347 + #
  348 + # It can modify the comment in several ways. In special, a plugin can call
  349 + # reject! on the comment and that will cause the comment to not be saved.
  350 + #
  351 + # example:
  352 + #
  353 + # def filter_comment(comment)
  354 + # if user_not_logged_in
  355 + # comment.reject!
  356 + # end
  357 + # end
  358 + #
  359 + def filter_comment(comment)
  360 + end
  361 +
  362 + # Define custom logic to filter loaded comments.
  363 + #
  364 + # Example:
  365 + #
  366 + # def unavailable_comments(scope)
  367 + # scope.without_spams
  368 + # end
  369 + #
  370 + def unavailable_comments(scope)
  371 + scope
  372 + end
  373 +
  374 + # -> Allows plugins to check weather object is a spam
  375 + def check_for_spam(object)
  376 + end
  377 +
  378 + # -> Allows plugins to know when an object is marked as a spam
  379 + def marked_as_spam(object)
  380 + end
  381 +
  382 + # -> Allows plugins to know when an object is marked as a ham
  383 + def marked_as_ham(object)
  384 + end
  385 +
  386 + # Adds extra actions for comments
  387 + # returns = list of hashes or lambda block that creates a list of hashes
  388 + # example:
  389 + #
  390 + # def comment_actions(comment)
  391 + # [{:link => link_to_function(...)}]
  392 + # end
  393 + #
  394 + def comment_actions(comment)
  395 + nil
  396 + end
  397 +
  398 + # This method is called when the user click on comment actions menu.
  399 + # returns = list or lambda block that return ids of enabled menu items for comments
  400 + # example:
  401 + #
  402 + # def check_comment_actions(comment)
  403 + # ['#action1', '#action2']
  404 + # end
  405 + #
  406 + def check_comment_actions(comment)
  407 + []
  408 + end
  409 +
  410 + # -> Adds adicional content to article
  411 + # returns = lambda block that creates html code
  412 + def article_extra_contents(article)
  413 + nil
  414 + end
  415 +
  416 + # -> Adds fields to the signup form
  417 + # returns = lambda block that creates html code
  418 + def signup_extra_contents
  419 + nil
  420 + end
  421 +
  422 + # -> Adds adicional content to profile info
  423 + # returns = lambda block that creates html code
  424 + def profile_info_extra_contents
  425 + nil
  426 + end
  427 +
  428 + # -> Removes the invite friend button from the friends controller
  429 + # returns = boolean
  430 + def remove_invite_friends_button
  431 + nil
  432 + end
  433 +
  434 + # -> Extends organization list of members
  435 + # returns = An instance of ActiveRecord::NamedScope::Scope retrieved through
  436 + # Person.members_of method.
  437 + def organization_members(organization)
  438 + nil
  439 + end
  440 +
  441 + # -> Extends person memberships list
  442 + # returns = An instance of ActiveRecord::NamedScope::Scope retrived through
  443 + # Person.memberships_of method.
  444 + def person_memberships(person)
  445 + nil
  446 + end
  447 +
  448 + # -> Extends person permission access
  449 + # returns = boolean
  450 + def has_permission?(person, permission, target)
  451 + nil
  452 + end
  453 +
  454 + # -> Adds hidden_fields to the new community view
  455 + # returns = {key => value}
  456 + def new_community_hidden_fields
  457 + nil
  458 + end
  459 +
  460 + # -> Adds hidden_fields to the enterprise registration view
  461 + # returns = {key => value}
  462 + def enterprise_registration_hidden_fields
  463 + nil
  464 + end
  465 +
  466 + # -> Add an alternative authentication method.
  467 + # Your plugin have to make the access control and return the logged user.
  468 + # returns = User
  469 + def alternative_authentication
  470 + nil
  471 + end
  472 +
  473 + # -> Adds adicional link to make the user authentication
  474 + # returns = lambda block that creates html code
  475 + def alternative_authentication_link
  476 + nil
  477 + end
  478 +
  479 + # -> Allow or not user registration
  480 + # returns = boolean
  481 + def allow_user_registration
  482 + true
  483 + end
  484 +
  485 + # -> Allow or not password recovery by users
  486 + # returns = boolean
  487 + def allow_password_recovery
  488 + true
  489 + end
  490 +
  491 + # -> Adds fields to the login form
  492 + # returns = lambda block that creates html code
  493 + def login_extra_contents
  494 + nil
  495 + end
  496 +
  497 + # -> Adds adicional content to comment form
  498 + # returns = lambda block that creates html code
  499 + def comment_form_extra_contents(args)
  500 + nil
  501 + end
  502 +
  503 + # -> Adds adicional content to article header
  504 + # returns = lambda block that creates html code
  505 + def article_header_extra_contents(article)
  506 + nil
  507 + end
  508 +
  509 + # -> Adds adittional content to comment visualization
  510 + # returns = lambda block that creates html code
  511 + def comment_extra_contents(args)
  512 + nil
  513 + end
  514 +
  515 + # This method is called when the user clicks to send a comment.
  516 + # A plugin can add new content to comment form and this method can process the params sent to avoid creating field on core tables.
  517 + # returns = params after processed by plugins
  518 + # example:
  519 + #
  520 + # def process_extra_comment_params(params)
  521 + # params.delete(:extra_field)
  522 + # end
  523 + #
  524 + def process_extra_comment_params(params)
  525 + params
  526 + end
  527 +
  528 + # -> Finds objects by their contents
  529 + # returns = {:results => [a, b, c, ...], ...}
  530 + # P.S.: The plugin might add other informations on the return hash for its
  531 + # own use in specific views
  532 + def find_by_contents(asset, scope, query, paginate_options={}, options={})
  533 + end
  534 +
  535 + # -> Adds aditional fields for change_password
  536 + # returns = [{:field => 'field1', :name => 'field 1 name', :model => 'person'}, {...}]
  537 + def change_password_fields
  538 + nil
  539 + end
  540 +
  541 + # -> Adds additional blocks to profiles and environments.
  542 + # Your plugin must implements a class method called 'extra_blocks'
  543 + # that returns a hash with the following syntax.
  544 + # {
  545 + # 'block_name' =>
  546 + # {
  547 + # :type => 'for which holder the block will be available',
  548 + # :position => 'where the block could be displayed'
  549 + # }
  550 + # }
  551 + #
  552 + # Where:
  553 + #
  554 + # - block_name: Name of the new block added to the blocks list
  555 + # - type: Might have some of the values
  556 + # - 'environment' or Environment: If the block is available only for Environment models
  557 + # - 'community' or Community: If the block is available only for Community models
  558 + # - 'enterprise' or Enterprise: If the block is available only for Enterprise models
  559 + # - 'person' or Person: If the block is available only for Person models
  560 + # - nil: If no type parameter is passed the block will be available for all types
  561 + # - position: Is the layout position of the block. It should be:
  562 + # - '1' or 1: Area 1 of layout
  563 + # - '2' or 2: Area 2 of layout
  564 + # - '3' or 3: Area 3 of layout
  565 + # - nil: If no position parameter is passed the block will be available for all positions
  566 + #
  567 + # OBS: Area 1 is where stay the main content of layout. Areas 2 and 3 are the sides of layout.
  568 + #
  569 + # examples:
  570 + #
  571 + # def self.extra_blocks(params)
  572 + # {
  573 + # #Display 'CustomBlock1' only for 'Person' on position '1'
  574 + # CustomBlock1 => {:type => 'person', :position => '1' },
  575 + #
  576 + # #Display 'CustomBlock2' only for 'Community' on position '2'
  577 + # CustomBlock2 => {:type => Community, :position => '2' },
  578 + #
  579 + # #Display 'CustomBlock3' only for 'Enterprise' on position '3'
  580 + # CustomBlock3 => {:type => 'enterprise', :position => 3 },
  581 + #
  582 + # #Display 'CustomBlock2' for 'Environment' and 'Person' on positions '1' and '3'
  583 + # CustomBlock4 => {:type => ['environment', Person], :position => ['1','3'] },
  584 + #
  585 + # #Display 'CustomBlock5' for all types and all positions
  586 + # CustomBlock5 => {},
  587 + # }
  588 + # end
  589 + #
  590 + # OBS: The default value is a empty hash.
  591 + def self.extra_blocks
  592 + {}
  593 + end
  594 +
  595 + def method_missing(method, *args, &block)
  596 + # This is a generic hotspot for all controllers on Noosfero.
  597 + # If any plugin wants to define filters to run on any controller, the name of
  598 + # the hotspot must be in the following form: <underscored_controller_name>_filters.
  599 + # Example: for ProfileController the hotspot is profile_controller_filters
  600 + #
  601 + # -> Adds a filter to a controller
  602 + # returns = { :type => type,
  603 + # :method_name => method_name,
  604 + # :options => {:opt1 => opt1, :opt2 => opt2},
  605 + # :block => Proc or lambda block}
  606 + # type = 'before_filter' or 'after_filter'
  607 + # method_name = The name of the filter
  608 + # option = Filter options, like :only or :except
  609 + # block = Block that the filter will call
  610 + if method.to_s =~ /^(.+)_controller_filters$/
  611 + []
  612 + # -> Removes the action button from the content
  613 + # returns = boolean
  614 + elsif method.to_s =~ /^content_remove_(#{content_actions.join('|')})$/
  615 + nil
  616 + # -> Expire the action button from the content
  617 + # returns = string with reason of expiration
  618 + elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/
  619 + nil
  620 + else
  621 + super
  622 + end
  623 + end
  624 +
  625 + private
  626 +
  627 + def content_actions
  628 + #FIXME 'new' and 'upload' only works for content_remove. It should work for
  629 + #content_expire too.
  630 + %w[edit delete spread locale suggest home new upload]
  631 + end
  632 +
  633 +end
  634 +
  635 +require 'noosfero/plugin/hot_spot'
  636 +require 'noosfero/plugin/manager'
  637 +require 'noosfero/plugin/active_record'
  638 +require 'noosfero/plugin/mailer_base'
  639 +require 'noosfero/plugin/settings'
... ...
lib/noosfero/role_assignment_ext.rb
... ... @@ -9,7 +9,7 @@ Rails.configuration.to_prepare do
9 9 #FIXME This will only work as long as the role_assignment associations
10 10 #happen only between profiles, due to the polymorphic column type.
11 11 if resource.role_assignments.where(:accessor_id => accessor.id).count == 1
12   - update_cache_counter(:members_count, resource, 1)
  12 + RoleAssignment.update_cache_counter(:members_count, resource, 1)
13 13 end
14 14 end
15 15 end
... ... @@ -21,7 +21,7 @@ Rails.configuration.to_prepare do
21 21 #FIXME This will only work as long as the role_assignment associations
22 22 #happen only between profiles, due to the polymorphic column type.
23 23 if resource.role_assignments.where(:accessor_id => accessor.id).count == 0
24   - update_cache_counter(:members_count, resource, -1)
  24 + RoleAssignment.update_cache_counter(:members_count, resource, -1)
25 25 end
26 26 end
27 27 end
... ...
test/unit/action_tracker_ext_test.rb
... ... @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 3 class ActionTrackerExtTest < ActiveSupport::TestCase
4 4 should 'increase person activities_count on new activity' do
5 5 person = fast_create(Person)
6   - assert_difference person, :activities_count, 1 do
  6 + assert_difference 'person.activities_count', 1 do
7 7 ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
8 8 person.reload
9 9 end
... ... @@ -13,7 +13,7 @@ class ActionTrackerExtTest &lt; ActiveSupport::TestCase
13 13 person = fast_create(Person)
14 14 record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => fast_create(Profile)
15 15 person.reload
16   - assert_difference person, :activities_count, -1 do
  16 + assert_difference 'person.activities_count', -1 do
17 17 record.destroy
18 18 person.reload
19 19 end
... ... @@ -25,7 +25,7 @@ class ActionTrackerExtTest &lt; ActiveSupport::TestCase
25 25 record.created_at = record.created_at - ActionTracker::Record::RECENT_DELAY.days - 1.day
26 26 record.save!
27 27 person.reload
28   - assert_no_difference person, :activities_count do
  28 + assert_no_difference 'person.activities_count' do
29 29 record.destroy
30 30 person.reload
31 31 end
... ... @@ -34,7 +34,7 @@ class ActionTrackerExtTest &lt; ActiveSupport::TestCase
34 34 should 'increase organization activities_count on new activity' do
35 35 person = fast_create(Person)
36 36 organization = fast_create(Organization)
37   - assert_difference organization, :activities_count, 1 do
  37 + assert_difference 'organization.activities_count', 1 do
38 38 ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
39 39 organization.reload
40 40 end
... ... @@ -45,7 +45,7 @@ class ActionTrackerExtTest &lt; ActiveSupport::TestCase
45 45 organization = fast_create(Organization)
46 46 record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization
47 47 organization.reload
48   - assert_difference organization, :activities_count, -1 do
  48 + assert_difference 'organization.activities_count', -1 do
49 49 record.destroy
50 50 organization.reload
51 51 end
... ... @@ -54,9 +54,9 @@ class ActionTrackerExtTest &lt; ActiveSupport::TestCase
54 54 should 'not decrease organization activities_count on activity removal after the recent delay' do
55 55 person = fast_create(Person)
56 56 organization = fast_create(Organization)
57   - record = ActionTracker::Record.create! :verb => :leave_scrap, :user => person, :target => organization, :created_at => (ActionTracker::Record::RECENT_DELAY + 1).days.ago
  57 + record = create(ActionTracker::Record, :verb => :leave_scrap, :user => person, :target => organization, :created_at => (ActionTracker::Record::RECENT_DELAY + 1).days.ago)
58 58 organization.reload
59   - assert_no_difference organization, :activities_count do
  59 + assert_no_difference 'organization.activities_count' do
60 60 record.destroy
61 61 organization.reload
62 62 end
... ...
test/unit/acts_as_having_settings_test.rb
... ... @@ -7,6 +7,7 @@ class ActsAsHavingSettingsTest &lt; ActiveSupport::TestCase
7 7 settings_items :flag, :type => :boolean
8 8 settings_items :flag_disabled_by_default, :type => :boolean, :default => false
9 9 settings_items :name, :type => :string, :default => N_('ENGLISH TEXT')
  10 + attr_accessible :flag, :name, :flag_disabled_by_default
10 11 end
11 12  
12 13 should 'store settings in a hash' do
... ...
test/unit/block_test.rb
... ... @@ -213,14 +213,14 @@ class BlockTest &lt; ActiveSupport::TestCase
213 213 end
214 214  
215 215 def display_even_context(context)
216   - context % 2 == 0
  216 + context[:value] % 2 == 0
217 217 end
218 218 end
219 219  
220 220 block = MyBlock.new
221 221  
222   - assert block.visible?(2)
223   - assert !block.visible?(3)
  222 + assert block.visible?({:value => 2})
  223 + assert !block.visible?({:value => 3})
224 224 end
225 225  
226 226 should 'not be embedable by default' do
... ...
test/unit/blog_helper_test.rb
... ... @@ -101,7 +101,7 @@ class BlogHelperTest &lt; ActionView::TestCase
101 101 end
102 102  
103 103 should 'display image if post is an image' do
104   - file = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile, :published => true, :parent => blog)
  104 + file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile, :published => true, :parent => blog)
105 105  
106 106 self.stubs(:params).returns({:npage => nil})
107 107  
... ...
test/unit/cms_helper_test.rb
... ... @@ -39,7 +39,7 @@ class CmsHelperTest &lt; ActionView::TestCase
39 39  
40 40 should 'display image and link if article is an image' do
41 41 profile = fast_create(Profile)
42   - file = create(UploadedFile, :profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
  42 + file = UploadedFile.create!(:profile => profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
43 43 file = FilePresenter.for file
44 44 icon = icon_for_article(file)
45 45 expects(:image_tag).with(icon).returns('icon')
... ...
test/unit/contact_sender_test.rb
... ... @@ -13,6 +13,7 @@ class ContactSenderTest &lt; ActiveSupport::TestCase
13 13  
14 14 should 'be able to deliver mail' do
15 15 ent = Environment.default.enterprises.new(:name => 'my enterprise', :identifier => 'myent')
  16 + Environment.default.update_attribute(:noreply_email, 'noreply@sample.org')
16 17 ent.contact_email = 'contact@invalid.com'
17 18 c = build(Contact, :dest => ent)
18 19 response = Contact::Sender.notification(c).deliver
... ...
test/unit/environment_test.rb
... ... @@ -1231,12 +1231,12 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
1231 1231 environment = fast_create(Environment)
1232 1232 environment.redirection_after_signup = 'invalid_option'
1233 1233 environment.save
1234   - assert environment.errors.invalid?(:redirection_after_signup)
  1234 + assert environment.errors[:redirection_after_signup.to_s].present?
1235 1235  
1236 1236 Environment.signup_redirection_options.keys.each do |redirection|
1237 1237 environment.redirection_after_signup = redirection
1238 1238 environment.save
1239   - assert !environment.errors.invalid?(:redirection_after_signup)
  1239 + assert !environment.errors[:redirection_after_signup.to_s].present?
1240 1240 end
1241 1241 end
1242 1242  
... ...
test/unit/folder_test.rb
... ... @@ -90,7 +90,7 @@ class FolderTest &lt; ActiveSupport::TestCase
90 90  
91 91 should 'return published images as images' do
92 92 person = create_user('test_user').person
93   - image = create(UploadedFile, :profile => person, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
  93 + image = UploadedFile.create!(:profile => person, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
94 94  
95 95 community = fast_create(Community)
96 96 folder = fast_create(Folder, :profile_id => community.id)
... ...
test/unit/gallery_test.rb
... ... @@ -98,7 +98,7 @@ class GalleryTest &lt; ActiveSupport::TestCase
98 98  
99 99 should 'return published images as images' do
100 100 p = create_user('test_user').person
101   - i = create(UploadedFile, :profile => p, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
  101 + i = UploadedFile.create!(:profile => p, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
102 102  
103 103 c = fast_create(Community)
104 104 gallery = fast_create(Gallery, :profile_id => c.id)
... ...
test/unit/organization_test.rb
... ... @@ -408,7 +408,7 @@ class OrganizationTest &lt; ActiveSupport::TestCase
408 408 should 'increase members_count on new membership' do
409 409 member = fast_create(Person)
410 410 organization = fast_create(Organization)
411   - assert_difference organization, :members_count, 1 do
  411 + assert_difference 'organization.members_count', 1 do
412 412 organization.add_member(member)
413 413 organization.reload
414 414 end
... ... @@ -419,7 +419,7 @@ class OrganizationTest &lt; ActiveSupport::TestCase
419 419 organization = fast_create(Organization)
420 420 organization.add_member(member)
421 421 organization.reload
422   - assert_difference organization, :members_count, -1 do
  422 + assert_difference 'organization.members_count', -1 do
423 423 organization.remove_member(member)
424 424 organization.reload
425 425 end
... ...
test/unit/person_notifier_helper_test.rb
1 1 require File.dirname(__FILE__) + '/../test_helper'
2 2  
3   -class PersonNotifierHelperTest < ActiveSupport::TestCase
  3 +class PersonNotifierHelperTest < ActionView::TestCase
4 4  
5 5 include PersonNotifierHelper
6   - include ActionView::Helpers::TagHelper
7 6  
8 7 def setup
9 8 @profile = mock
... ...
test/unit/person_notifier_test.rb
... ... @@ -8,7 +8,7 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
8 8 ActionMailer::Base.delivery_method = :test
9 9 ActionMailer::Base.perform_deliveries = true
10 10 ActionMailer::Base.deliveries = []
11   - Person.destroy_all
  11 + Person.delete_all
12 12 @admin = create_user('adminuser').person
13 13 @member = create_user('member').person
14 14 @admin.notification_time = 24
... ... @@ -26,7 +26,7 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
26 26 should 'deliver mail to community members' do
27 27 @community.add_member(@member)
28 28 notify
29   - sent = ActionMailer::Base.deliveries.first
  29 + sent = ActionMailer::Base.deliveries.last
30 30 assert_equal [@member.email], sent.to
31 31 end
32 32  
... ... @@ -48,7 +48,7 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
48 48 Comment.create!(:author => @admin, :title => 'test comment', :body => 'body!', :source => @article)
49 49 notify
50 50 sent = ActionMailer::Base.deliveries.first
51   - assert_match /#{@admin.name}/, sent.body
  51 + assert_match /#{@admin.name}/, sent.body.to_s
52 52 end
53 53  
54 54 should 'do not include comment created before last notification' do
... ... @@ -79,20 +79,20 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
79 79 should 'schedule next mail at notification time' do
80 80 @member.notification_time = 12
81 81 @member.notifier.schedule_next_notification_mail
82   - assert_equal @member.notification_time, DateTime.now.hour - Delayed::Job.first.run_at.hour
  82 + assert_equal @member.notification_time, DateTime.now.hour - Delayed::Job.last.run_at.hour
83 83 end
84 84  
85 85 should 'do not schedule duplicated notification mail' do
86 86 @member.notification_time = 12
87 87 @member.notifier.schedule_next_notification_mail
88 88 @member.notifier.schedule_next_notification_mail
89   - assert_equal 1, Delayed::Job.count
  89 + assert_equal 1, PersonNotifier::NotifyJob.find(@member.id).count
90 90 end
91 91  
92 92 should 'do not schedule next mail if notification time is zero' do
93 93 @member.notification_time = 0
94 94 @member.notifier.schedule_next_notification_mail
95   - assert_equal 0, Delayed::Job.count
  95 + assert !PersonNotifier::NotifyJob.exists?(@member.id)
96 96 end
97 97  
98 98 should 'schedule next notifications for all person with notification time greater than zero' do
... ... @@ -107,28 +107,30 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
107 107 end
108 108  
109 109 should 'do not create duplicated job' do
110   - PersonNotifier.schedule_all_next_notification_mail
111   - PersonNotifier.schedule_all_next_notification_mail
112   - assert_equal 1, Delayed::Job.count
  110 + assert_difference 'Delayed::Job.count', 1 do
  111 + PersonNotifier.schedule_all_next_notification_mail
  112 + PersonNotifier.schedule_all_next_notification_mail
  113 + end
113 114 end
114 115  
115 116 should 'schedule after update and set a valid notification time' do
116 117 @member.notification_time = 0
117 118 @member.save!
118   - assert_equal 0, Delayed::Job.count
  119 + assert !PersonNotifier::NotifyJob.exists?(@member.id)
119 120 @member.notification_time = 12
120 121 @member.save!
121   - assert_equal 1, Delayed::Job.count
  122 + assert PersonNotifier::NotifyJob.exists?(@member.id)
122 123 end
123 124  
124 125 should 'reschedule with changed notification time' do
125 126 @member.notification_time = 2
126 127 @member.save!
127   - assert_equal 1, Delayed::Job.count
  128 + assert PersonNotifier::NotifyJob.exists?(@member.id)
128 129 @member.notification_time = 12
129 130 @member.save!
130   - assert_equal 1, Delayed::Job.count
131   - assert_equal @member.notification_time, DateTime.now.hour - Delayed::Job.first.run_at.hour
  131 + jobs = PersonNotifier::NotifyJob.find(@member.id)
  132 + assert_equal 1, jobs.count
  133 + assert_equal @member.notification_time, DateTime.now.hour - jobs.last.run_at.hour
132 134 end
133 135  
134 136 should 'display error message if fail to render a notificiation' do
... ... @@ -137,7 +139,7 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
137 139 ActionTracker::Record.any_instance.stubs(:verb).returns("some_invalid_verb")
138 140 notify
139 141 sent = ActionMailer::Base.deliveries.first
140   - assert_match /cannot render notification for some_invalid_verb/, sent.body
  142 + assert_match /cannot render notification for some_invalid_verb/, sent.body.to_s
141 143 end
142 144  
143 145 ActionTrackerConfig.verb_names.each do |verb|
... ... @@ -158,7 +160,7 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
158 160  
159 161 notify
160 162 sent = ActionMailer::Base.deliveries.first
161   - assert_no_match /cannot render notification for #{verb}/, sent.body
  163 + assert_no_match /cannot render notification for #{verb}/, sent.body.to_s
162 164 end
163 165 end
164 166  
... ... @@ -193,16 +195,15 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
193 195 assert_equal 1, Delayed::Job.count
194 196 end
195 197  
196   - should 'NotifyJob failed jobs create a new NotifyJob on permanent failure' do
  198 + should 'NotifyJob failed jobs create a new NotifyJob on failure' do
  199 + Delayed::Worker.max_attempts = 1
197 200 Delayed::Job.enqueue(PersonNotifier::NotifyJob.new(@member.id))
198 201  
199 202 PersonNotifier.any_instance.stubs(:notify).raises('error')
200 203  
201 204 process_delayed_job_queue
202   - jobs = Delayed::Job.all
203   -
204   - assert 1, jobs.select{|j| j.failed?}.size
205   - assert 1, jobs.select{|j| !j.failed?}.size
  205 + jobs = PersonNotifier::NotifyJob.find(@member.id)
  206 + assert !jobs.select {|j| !j.failed? && j.last_error.nil? }.empty?
206 207 end
207 208  
208 209 def notify
... ...
test/unit/person_test.rb
... ... @@ -1450,8 +1450,8 @@ class PersonTest &lt; ActiveSupport::TestCase
1450 1450 should 'increase friends_count on new friendship' do
1451 1451 person = create_user('person').person
1452 1452 friend = create_user('friend').person
1453   - assert_difference person, :friends_count, 1 do
1454   - assert_difference friend, :friends_count, 1 do
  1453 + assert_difference 'person.friends_count', 1 do
  1454 + assert_difference 'friend.friends_count', 1 do
1455 1455 person.add_friend(friend)
1456 1456 friend.reload
1457 1457 end
... ... @@ -1465,8 +1465,8 @@ class PersonTest &lt; ActiveSupport::TestCase
1465 1465 person.add_friend(friend)
1466 1466 friend.reload
1467 1467 person.reload
1468   - assert_difference person, :friends_count, -1 do
1469   - assert_difference friend, :friends_count, -1 do
  1468 + assert_difference 'person.friends_count', -1 do
  1469 + assert_difference 'friend.friends_count', -1 do
1470 1470 person.remove_friend(friend)
1471 1471 friend.reload
1472 1472 end
... ...
test/unit/role_assignment_ext_test.rb
... ... @@ -6,9 +6,9 @@ class RoleAssignmentExtTest &lt; ActiveSupport::TestCase
6 6 role2 = Role.create!(:name => 'role2')
7 7 member = create_user('person').person
8 8 organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
9   - assert_difference organization, :members_count, 1 do
10   - RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
11   - RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  9 + assert_difference 'organization.members_count', 1 do
  10 + create(RoleAssignment, :accessor => member, :resource => organization, :role => role1)
  11 + create(RoleAssignment, :accessor => member, :resource => organization, :role => role2)
12 12 organization.reload
13 13 end
14 14 end
... ... @@ -18,10 +18,10 @@ class RoleAssignmentExtTest &lt; ActiveSupport::TestCase
18 18 role2 = Role.create!(:name => 'role2')
19 19 member = create_user('person').person
20 20 organization = Organization.create!(:name => 'Organization', :identifier => 'organization')
21   - RoleAssignment.create!(:accessor => member, :resource => organization, :role => role1)
22   - RoleAssignment.create!(:accessor => member, :resource => organization, :role => role2)
  21 + create(RoleAssignment, :accessor => member, :resource => organization, :role => role1)
  22 + create(RoleAssignment, :accessor => member, :resource => organization, :role => role2)
23 23 organization.reload
24   - assert_difference organization, :members_count, -1 do
  24 + assert_difference 'organization.members_count', -1 do
25 25 organization.role_assignments.destroy_all
26 26 organization.reload
27 27 end
... ...
test/unit/uploaded_file_test.rb
... ... @@ -129,7 +129,7 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
129 129 end
130 130  
131 131 should 'always provide a display title' do
132   - upload = build(UploadedFile, :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'))
  132 + upload = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'))
133 133 assert_equal 'test.txt', upload.title
134 134 upload.title = 'My text file'
135 135 assert_equal 'My text file', upload.title
... ... @@ -327,10 +327,10 @@ class UploadedFileTest &lt; ActiveSupport::TestCase
327 327 ActionTracker::Record.delete_all
328 328 gallery = fast_create(Gallery, :profile_id => profile.id)
329 329  
330   - image1 = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile)
  330 + image1 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => profile)
331 331 assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
332 332  
333   - image2 = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :parent => gallery, :profile => profile)
  333 + image2 = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/other-pic.jpg', 'image/jpg'), :parent => gallery, :profile => profile)
334 334 assert_equal 1, ActionTracker::Record.find_all_by_verb('upload_image').count
335 335 end
336 336  
... ...