From 6f5707c2b54d5a3ced1f63c31e67f863f1b46a37 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Fri, 4 Mar 2011 14:32:58 +0000 Subject: [PATCH] Adds email notifications support for news comments (#2074). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@5003 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/controllers/news_controller.rb | 6 +++-- app/models/comment_observer.rb | 24 +++++++++++++++++++ app/models/mailer.rb | 22 +++++++++++++++-- app/models/news.rb | 11 ++++++++- .../mailer/news_comment_added.text.html.rhtml | 5 ++++ .../news_comment_added.text.plain.rhtml | 6 +++++ app/views/news/show.rhtml | 1 + config/environment.rb | 2 +- config/locales/en.yml | 1 + config/locales/fr.yml | 1 + lib/redmine/notifiable.rb | 1 + test/unit/comment_test.rb | 13 ++++++++-- test/unit/lib/redmine/notifiable_test.rb | 8 +++---- test/unit/mailer_test.rb | 14 ++++++++--- 14 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 app/models/comment_observer.rb create mode 100644 app/views/mailer/news_comment_added.text.html.rhtml create mode 100644 app/views/mailer/news_comment_added.text.plain.rhtml diff --git a/app/controllers/news_controller.rb b/app/controllers/news_controller.rb index e7c643e9..bc7eabb5 100644 --- a/app/controllers/news_controller.rb +++ b/app/controllers/news_controller.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -25,6 +25,8 @@ class NewsController < ApplicationController before_filter :find_optional_project, :only => :index accept_key_auth :index + helper :watchers + def index case params[:format] when 'xml', 'json' diff --git a/app/models/comment_observer.rb b/app/models/comment_observer.rb new file mode 100644 index 00000000..fc008942 --- /dev/null +++ b/app/models/comment_observer.rb @@ -0,0 +1,24 @@ +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class CommentObserver < ActiveRecord::Observer + def after_create(comment) + if comment.commented.is_a?(News) && Setting.notified_events.include?('news_comment_added') + Mailer.deliver_news_comment_added(comment) + end + end +end diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 8ad2c179..fbda2180 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -154,6 +154,24 @@ class Mailer < ActionMailer::Base :news_url => url_for(:controller => 'news', :action => 'show', :id => news) render_multipart('news_added', body) end + + # Builds a tmail object used to email recipients of a news' project when a news comment is added. + # + # Example: + # news_comment_added(comment) => tmail object + # Mailer.news_comment_added(comment) => sends an email to the news' project recipients + def news_comment_added(comment) + news = comment.commented + redmine_headers 'Project' => news.project.identifier + message_id comment + recipients news.recipients + cc news.watcher_recipients + subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" + body :news => news, + :comment => comment, + :news_url => url_for(:controller => 'news', :action => 'show', :id => news) + render_multipart('news_comment_added', body) + end # Builds a tmail object used to email the recipients of the specified message that was posted. # diff --git a/app/models/news.rb b/app/models/news.rb index 00729f06..7f8c7310 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -1,5 +1,5 @@ # Redmine - project management software -# Copyright (C) 2006-2008 Jean-Philippe Lang +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -28,6 +28,9 @@ class News < ActiveRecord::Base acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} acts_as_activity_provider :find_options => {:include => [:project, :author]}, :author_key => :author_id + acts_as_watchable + + after_create :add_author_as_watcher named_scope :visible, lambda {|*args| { :include => :project, @@ -42,4 +45,10 @@ class News < ActiveRecord::Base def self.latest(user = User.current, count = 5) find(:all, :limit => count, :conditions => Project.allowed_to_condition(user, :view_news), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") end + + private + + def add_author_as_watcher + Watcher.create(:watchable => self, :user => author) + end end diff --git a/app/views/mailer/news_comment_added.text.html.rhtml b/app/views/mailer/news_comment_added.text.html.rhtml new file mode 100644 index 00000000..ef2be0f6 --- /dev/null +++ b/app/views/mailer/news_comment_added.text.html.rhtml @@ -0,0 +1,5 @@ +

<%= link_to(h(@news.title), @news_url) %>

+ +

<%= l(:text_user_wrote, :value => h(@comment.author)) %>

+ +<%= textilizable @comment, :comments, :only_path => false %> diff --git a/app/views/mailer/news_comment_added.text.plain.rhtml b/app/views/mailer/news_comment_added.text.plain.rhtml new file mode 100644 index 00000000..aadbc37c --- /dev/null +++ b/app/views/mailer/news_comment_added.text.plain.rhtml @@ -0,0 +1,6 @@ +<%= @news.title %> +<%= @news_url %> + +<%= l(:text_user_wrote, :value => @comment.author) %> + +<%= @comment.comments %> diff --git a/app/views/news/show.rhtml b/app/views/news/show.rhtml index 0dc3fe35..28db44e9 100644 --- a/app/views/news/show.rhtml +++ b/app/views/news/show.rhtml @@ -1,4 +1,5 @@
+<%= watcher_tag(@news, User.current) %> <%= link_to(l(:button_edit), edit_news_path(@news), :class => 'icon icon-edit', diff --git a/config/environment.rb b/config/environment.rb index 91dfaa42..00e81517 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -36,7 +36,7 @@ Rails::Initializer.run do |config| # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector - config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer + config.active_record.observers = :message_observer, :issue_observer, :journal_observer, :news_observer, :document_observer, :wiki_content_observer, :comment_observer # Make Active Record use UTC-base instead of local time # config.active_record.default_timezone = :utc diff --git a/config/locales/en.yml b/config/locales/en.yml index c0fb8fca..3649fe23 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -537,6 +537,7 @@ en: label_news_latest: Latest news label_news_view_all: View all news label_news_added: News added + label_news_comment_added: Comment added to a news label_settings: Settings label_overview: Overview label_version: Version diff --git a/config/locales/fr.yml b/config/locales/fr.yml index b3a60ba7..356f3799 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -539,6 +539,7 @@ fr: label_news_latest: Dernières annonces label_news_view_all: Voir toutes les annonces label_news_added: Annonce ajoutée + label_news_comment_added: Commentaire ajouté à une annonce label_settings: Configuration label_overview: Aperçu label_version: Version diff --git a/lib/redmine/notifiable.rb b/lib/redmine/notifiable.rb index 71d1ba50..37d4a407 100644 --- a/lib/redmine/notifiable.rb +++ b/lib/redmine/notifiable.rb @@ -14,6 +14,7 @@ module Redmine notifications << Notifiable.new('issue_status_updated', 'issue_updated') notifications << Notifiable.new('issue_priority_updated', 'issue_updated') notifications << Notifiable.new('news_added') + notifications << Notifiable.new('news_comment_added') notifications << Notifiable.new('document_added') notifications << Notifiable.new('file_added') notifications << Notifiable.new('message_posted') diff --git a/test/unit/comment_test.rb b/test/unit/comment_test.rb index 43265c47..02be8fc5 100644 --- a/test/unit/comment_test.rb +++ b/test/unit/comment_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -31,6 +31,15 @@ class CommentTest < ActiveSupport::TestCase @news.reload assert_equal 2, @news.comments_count end + + def test_create_should_send_notification + Setting.notified_events << 'news_comment_added' + Watcher.create!(:watchable => @news, :user => @jsmith) + + assert_difference 'ActionMailer::Base.deliveries.size' do + Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment") + end + end def test_validate comment = Comment.new(:commented => @news) diff --git a/test/unit/lib/redmine/notifiable_test.rb b/test/unit/lib/redmine/notifiable_test.rb index fe02fbfc..7ca44920 100644 --- a/test/unit/lib/redmine/notifiable_test.rb +++ b/test/unit/lib/redmine/notifiable_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2008 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -22,9 +22,9 @@ class Redmine::NotifiableTest < ActiveSupport::TestCase end def test_all - assert_equal 11, Redmine::Notifiable.all.length + assert_equal 12, Redmine::Notifiable.all.length - %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable| + %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_added news_comment_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable| assert Redmine::Notifiable.all.collect(&:name).include?(notifiable), "missing #{notifiable}" end end diff --git a/test/unit/mailer_test.rb b/test/unit/mailer_test.rb index ae7c06d3..36ed4fe9 100644 --- a/test/unit/mailer_test.rb +++ b/test/unit/mailer_test.rb @@ -1,5 +1,5 @@ -# redMine - project management software -# Copyright (C) 2006-2007 Jean-Philippe Lang +# Redmine - project management software +# Copyright (C) 2006-2011 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -20,7 +20,7 @@ require File.expand_path('../../test_helper', __FILE__) class MailerTest < ActiveSupport::TestCase include Redmine::I18n include ActionController::Assertions::SelectorAssertions - fixtures :projects, :enabled_modules, :issues, :users, :members, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories + fixtures :all def setup ActionMailer::Base.deliveries.clear @@ -295,6 +295,14 @@ class MailerTest < ActiveSupport::TestCase end end + def test_news_comment_added + comment = Comment.find(2) + valid_languages.each do |lang| + Setting.default_language = lang.to_s + assert Mailer.deliver_news_comment_added(comment) + end + end + def test_message_posted message = Message.find(:first) recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}