##// END OF EJS Templates
Fixed: auto closing of duplicates doesn't work....
Jean-Philippe Lang -
r1148:652dc1a73af8
parent child
Show More
@@ -1,228 +1,232
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Issue < ActiveRecord::Base
18 class Issue < ActiveRecord::Base
19 belongs_to :project
19 belongs_to :project
20 belongs_to :tracker
20 belongs_to :tracker
21 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
21 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
22 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
22 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
23 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
23 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
24 belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
24 belongs_to :fixed_version, :class_name => 'Version', :foreign_key => 'fixed_version_id'
25 belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
25 belongs_to :priority, :class_name => 'Enumeration', :foreign_key => 'priority_id'
26 belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
26 belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id'
27
27
28 has_many :journals, :as => :journalized, :dependent => :destroy
28 has_many :journals, :as => :journalized, :dependent => :destroy
29 has_many :attachments, :as => :container, :dependent => :destroy
29 has_many :attachments, :as => :container, :dependent => :destroy
30 has_many :time_entries, :dependent => :nullify
30 has_many :time_entries, :dependent => :nullify
31 has_many :custom_values, :dependent => :delete_all, :as => :customized
31 has_many :custom_values, :dependent => :delete_all, :as => :customized
32 has_many :custom_fields, :through => :custom_values
32 has_many :custom_fields, :through => :custom_values
33 has_and_belongs_to_many :changesets, :order => "revision ASC"
33 has_and_belongs_to_many :changesets, :order => "revision ASC"
34
34
35 has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
35 has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all
36 has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
36 has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all
37
37
38 acts_as_watchable
38 acts_as_watchable
39 acts_as_searchable :columns => ['subject', 'description'], :with => {:journal => :issue}
39 acts_as_searchable :columns => ['subject', 'description'], :with => {:journal => :issue}
40 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
40 acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"},
41 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
41 :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}}
42
42
43 validates_presence_of :subject, :description, :priority, :project, :tracker, :author, :status
43 validates_presence_of :subject, :description, :priority, :project, :tracker, :author, :status
44 validates_length_of :subject, :maximum => 255
44 validates_length_of :subject, :maximum => 255
45 validates_inclusion_of :done_ratio, :in => 0..100
45 validates_inclusion_of :done_ratio, :in => 0..100
46 validates_numericality_of :estimated_hours, :allow_nil => true
46 validates_numericality_of :estimated_hours, :allow_nil => true
47 validates_associated :custom_values, :on => :update
47 validates_associated :custom_values, :on => :update
48
48
49 def after_initialize
49 def after_initialize
50 if new_record?
50 if new_record?
51 # set default values for new records only
51 # set default values for new records only
52 self.status ||= IssueStatus.default
52 self.status ||= IssueStatus.default
53 self.priority ||= Enumeration.default('IPRI')
53 self.priority ||= Enumeration.default('IPRI')
54 end
54 end
55 end
55 end
56
56
57 def copy_from(arg)
57 def copy_from(arg)
58 issue = arg.is_a?(Issue) ? arg : Issue.find(arg)
58 issue = arg.is_a?(Issue) ? arg : Issue.find(arg)
59 self.attributes = issue.attributes.dup
59 self.attributes = issue.attributes.dup
60 self.custom_values = issue.custom_values.collect {|v| v.clone}
60 self.custom_values = issue.custom_values.collect {|v| v.clone}
61 self
61 self
62 end
62 end
63
63
64 # Move an issue to a new project and tracker
64 # Move an issue to a new project and tracker
65 def move_to(new_project, new_tracker = nil)
65 def move_to(new_project, new_tracker = nil)
66 transaction do
66 transaction do
67 if new_project && project_id != new_project.id
67 if new_project && project_id != new_project.id
68 # delete issue relations
68 # delete issue relations
69 self.relations_from.clear
69 self.relations_from.clear
70 self.relations_to.clear
70 self.relations_to.clear
71 # issue is moved to another project
71 # issue is moved to another project
72 self.category = nil
72 self.category = nil
73 self.fixed_version = nil
73 self.fixed_version = nil
74 self.project = new_project
74 self.project = new_project
75 end
75 end
76 if new_tracker
76 if new_tracker
77 self.tracker = new_tracker
77 self.tracker = new_tracker
78 end
78 end
79 if save
79 if save
80 # Manually update project_id on related time entries
80 # Manually update project_id on related time entries
81 TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
81 TimeEntry.update_all("project_id = #{new_project.id}", {:issue_id => id})
82 else
82 else
83 rollback_db_transaction
83 rollback_db_transaction
84 return false
84 return false
85 end
85 end
86 end
86 end
87 return true
87 return true
88 end
88 end
89
89
90 def priority_id=(pid)
90 def priority_id=(pid)
91 self.priority = nil
91 self.priority = nil
92 write_attribute(:priority_id, pid)
92 write_attribute(:priority_id, pid)
93 end
93 end
94
94
95 def validate
95 def validate
96 if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
96 if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
97 errors.add :due_date, :activerecord_error_not_a_date
97 errors.add :due_date, :activerecord_error_not_a_date
98 end
98 end
99
99
100 if self.due_date and self.start_date and self.due_date < self.start_date
100 if self.due_date and self.start_date and self.due_date < self.start_date
101 errors.add :due_date, :activerecord_error_greater_than_start_date
101 errors.add :due_date, :activerecord_error_greater_than_start_date
102 end
102 end
103
103
104 if start_date && soonest_start && start_date < soonest_start
104 if start_date && soonest_start && start_date < soonest_start
105 errors.add :start_date, :activerecord_error_invalid
105 errors.add :start_date, :activerecord_error_invalid
106 end
106 end
107 end
107 end
108
108
109 def validate_on_create
109 def validate_on_create
110 errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
110 errors.add :tracker_id, :activerecord_error_invalid unless project.trackers.include?(tracker)
111 end
111 end
112
112
113 def before_create
113 def before_create
114 # default assignment based on category
114 # default assignment based on category
115 if assigned_to.nil? && category && category.assigned_to
115 if assigned_to.nil? && category && category.assigned_to
116 self.assigned_to = category.assigned_to
116 self.assigned_to = category.assigned_to
117 end
117 end
118 end
118 end
119
119
120 def before_save
120 def before_save
121 if @current_journal
121 if @current_journal
122 # attributes changes
122 # attributes changes
123 (Issue.column_names - %w(id description)).each {|c|
123 (Issue.column_names - %w(id description)).each {|c|
124 @current_journal.details << JournalDetail.new(:property => 'attr',
124 @current_journal.details << JournalDetail.new(:property => 'attr',
125 :prop_key => c,
125 :prop_key => c,
126 :old_value => @issue_before_change.send(c),
126 :old_value => @issue_before_change.send(c),
127 :value => send(c)) unless send(c)==@issue_before_change.send(c)
127 :value => send(c)) unless send(c)==@issue_before_change.send(c)
128 }
128 }
129 # custom fields changes
129 # custom fields changes
130 custom_values.each {|c|
130 custom_values.each {|c|
131 next if (@custom_values_before_change[c.custom_field_id]==c.value ||
131 next if (@custom_values_before_change[c.custom_field_id]==c.value ||
132 (@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?))
132 (@custom_values_before_change[c.custom_field_id].blank? && c.value.blank?))
133 @current_journal.details << JournalDetail.new(:property => 'cf',
133 @current_journal.details << JournalDetail.new(:property => 'cf',
134 :prop_key => c.custom_field_id,
134 :prop_key => c.custom_field_id,
135 :old_value => @custom_values_before_change[c.custom_field_id],
135 :old_value => @custom_values_before_change[c.custom_field_id],
136 :value => c.value)
136 :value => c.value)
137 }
137 }
138 @current_journal.save
138 @current_journal.save
139 end
139 end
140 # Save the issue even if the journal is not saved (because empty)
140 # Save the issue even if the journal is not saved (because empty)
141 true
141 true
142 end
142 end
143
143
144 def after_save
144 def after_save
145 # Reload is needed in order to get the right status
146 reload
147
145 # Update start/due dates of following issues
148 # Update start/due dates of following issues
146 relations_from.each(&:set_issue_to_dates)
149 relations_from.each(&:set_issue_to_dates)
147
150
148 # Close duplicates if the issue was closed
151 # Close duplicates if the issue was closed
149 if @issue_before_change && !@issue_before_change.closed? && self.closed?
152 if @issue_before_change && !@issue_before_change.closed? && self.closed?
150 duplicates.each do |duplicate|
153 duplicates.each do |duplicate|
151 # Don't re-close it if it's already closed
154 # Don't re-close it if it's already closed
152 next if duplicate.closed?
155 next if duplicate.closed?
153 # Same user and notes
156 # Same user and notes
154 duplicate.init_journal(@current_journal.user, @current_journal.notes)
157 duplicate.init_journal(@current_journal.user, @current_journal.notes)
155 duplicate.update_attribute :status, self.status
158 duplicate.update_attribute :status, self.status
156 end
159 end
157 end
160 end
158 end
161 end
159
162
160 def custom_value_for(custom_field)
163 def custom_value_for(custom_field)
161 self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
164 self.custom_values.each {|v| return v if v.custom_field_id == custom_field.id }
162 return nil
165 return nil
163 end
166 end
164
167
165 def init_journal(user, notes = "")
168 def init_journal(user, notes = "")
166 @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
169 @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes)
167 @issue_before_change = self.clone
170 @issue_before_change = self.clone
171 @issue_before_change.status = self.status
168 @custom_values_before_change = {}
172 @custom_values_before_change = {}
169 self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
173 self.custom_values.each {|c| @custom_values_before_change.store c.custom_field_id, c.value }
170 @current_journal
174 @current_journal
171 end
175 end
172
176
173 # Return true if the issue is closed, otherwise false
177 # Return true if the issue is closed, otherwise false
174 def closed?
178 def closed?
175 self.status.is_closed?
179 self.status.is_closed?
176 end
180 end
177
181
178 # Users the issue can be assigned to
182 # Users the issue can be assigned to
179 def assignable_users
183 def assignable_users
180 project.assignable_users
184 project.assignable_users
181 end
185 end
182
186
183 # Returns an array of status that user is able to apply
187 # Returns an array of status that user is able to apply
184 def new_statuses_allowed_to(user)
188 def new_statuses_allowed_to(user)
185 statuses = status.find_new_statuses_allowed_to(user.role_for_project(project), tracker)
189 statuses = status.find_new_statuses_allowed_to(user.role_for_project(project), tracker)
186 statuses << status unless statuses.empty?
190 statuses << status unless statuses.empty?
187 statuses.uniq.sort
191 statuses.uniq.sort
188 end
192 end
189
193
190 # Returns the mail adresses of users that should be notified for the issue
194 # Returns the mail adresses of users that should be notified for the issue
191 def recipients
195 def recipients
192 recipients = project.recipients
196 recipients = project.recipients
193 # Author and assignee are always notified unless they have been locked
197 # Author and assignee are always notified unless they have been locked
194 recipients << author.mail if author && author.active?
198 recipients << author.mail if author && author.active?
195 recipients << assigned_to.mail if assigned_to && assigned_to.active?
199 recipients << assigned_to.mail if assigned_to && assigned_to.active?
196 recipients.compact.uniq
200 recipients.compact.uniq
197 end
201 end
198
202
199 def spent_hours
203 def spent_hours
200 @spent_hours ||= time_entries.sum(:hours) || 0
204 @spent_hours ||= time_entries.sum(:hours) || 0
201 end
205 end
202
206
203 def relations
207 def relations
204 (relations_from + relations_to).sort
208 (relations_from + relations_to).sort
205 end
209 end
206
210
207 def all_dependent_issues
211 def all_dependent_issues
208 dependencies = []
212 dependencies = []
209 relations_from.each do |relation|
213 relations_from.each do |relation|
210 dependencies << relation.issue_to
214 dependencies << relation.issue_to
211 dependencies += relation.issue_to.all_dependent_issues
215 dependencies += relation.issue_to.all_dependent_issues
212 end
216 end
213 dependencies
217 dependencies
214 end
218 end
215
219
216 # Returns an array of the duplicate issues
220 # Returns an array of the duplicate issues
217 def duplicates
221 def duplicates
218 relations.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.other_issue(self)}
222 relations.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.other_issue(self)}
219 end
223 end
220
224
221 def duration
225 def duration
222 (start_date && due_date) ? due_date - start_date : 0
226 (start_date && due_date) ? due_date - start_date : 0
223 end
227 end
224
228
225 def soonest_start
229 def soonest_start
226 @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
230 @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
227 end
231 end
228 end
232 end
@@ -1,164 +1,163
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Mailer < ActionMailer::Base
18 class Mailer < ActionMailer::Base
19 helper ApplicationHelper
19 helper ApplicationHelper
20 helper IssuesHelper
20 helper IssuesHelper
21 helper CustomFieldsHelper
21 helper CustomFieldsHelper
22
22
23 include ActionController::UrlWriter
23 include ActionController::UrlWriter
24
24
25 def issue_add(issue)
25 def issue_add(issue)
26 recipients issue.recipients
26 recipients issue.recipients
27 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
27 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
28 body :issue => issue,
28 body :issue => issue,
29 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
29 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
30 end
30 end
31
31
32 def issue_edit(journal)
32 def issue_edit(journal)
33 issue = journal.journalized
33 issue = journal.journalized
34 issue.reload
35 recipients issue.recipients
34 recipients issue.recipients
36 # Watchers in cc
35 # Watchers in cc
37 cc(issue.watcher_recipients - @recipients)
36 cc(issue.watcher_recipients - @recipients)
38 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
37 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
39 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
38 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
40 s << issue.subject
39 s << issue.subject
41 subject s
40 subject s
42 body :issue => issue,
41 body :issue => issue,
43 :journal => journal,
42 :journal => journal,
44 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
43 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
45 end
44 end
46
45
47 def document_added(document)
46 def document_added(document)
48 recipients document.project.recipients
47 recipients document.project.recipients
49 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
48 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
50 body :document => document,
49 body :document => document,
51 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
50 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
52 end
51 end
53
52
54 def attachments_added(attachments)
53 def attachments_added(attachments)
55 container = attachments.first.container
54 container = attachments.first.container
56 added_to = ''
55 added_to = ''
57 added_to_url = ''
56 added_to_url = ''
58 case container.class.name
57 case container.class.name
59 when 'Version'
58 when 'Version'
60 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
59 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
61 added_to = "#{l(:label_version)}: #{container.name}"
60 added_to = "#{l(:label_version)}: #{container.name}"
62 when 'Document'
61 when 'Document'
63 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
62 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
64 added_to = "#{l(:label_document)}: #{container.title}"
63 added_to = "#{l(:label_document)}: #{container.title}"
65 end
64 end
66 recipients container.project.recipients
65 recipients container.project.recipients
67 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
66 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
68 body :attachments => attachments,
67 body :attachments => attachments,
69 :added_to => added_to,
68 :added_to => added_to,
70 :added_to_url => added_to_url
69 :added_to_url => added_to_url
71 end
70 end
72
71
73 def news_added(news)
72 def news_added(news)
74 recipients news.project.recipients
73 recipients news.project.recipients
75 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
74 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
76 body :news => news,
75 body :news => news,
77 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
76 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
78 end
77 end
79
78
80 def message_posted(message, recipients)
79 def message_posted(message, recipients)
81 recipients(recipients)
80 recipients(recipients)
82 subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
81 subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
83 body :message => message,
82 body :message => message,
84 :message_url => url_for(:controller => 'messages', :action => 'show', :board_id => message.board_id, :id => message.root)
83 :message_url => url_for(:controller => 'messages', :action => 'show', :board_id => message.board_id, :id => message.root)
85 end
84 end
86
85
87 def account_information(user, password)
86 def account_information(user, password)
88 set_language_if_valid user.language
87 set_language_if_valid user.language
89 recipients user.mail
88 recipients user.mail
90 subject l(:mail_subject_register)
89 subject l(:mail_subject_register)
91 body :user => user,
90 body :user => user,
92 :password => password,
91 :password => password,
93 :login_url => url_for(:controller => 'account', :action => 'login')
92 :login_url => url_for(:controller => 'account', :action => 'login')
94 end
93 end
95
94
96 def account_activation_request(user)
95 def account_activation_request(user)
97 # Send the email to all active administrators
96 # Send the email to all active administrators
98 recipients User.find_active(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
97 recipients User.find_active(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
99 subject l(:mail_subject_account_activation_request)
98 subject l(:mail_subject_account_activation_request)
100 body :user => user,
99 body :user => user,
101 :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
100 :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
102 end
101 end
103
102
104 def lost_password(token)
103 def lost_password(token)
105 set_language_if_valid(token.user.language)
104 set_language_if_valid(token.user.language)
106 recipients token.user.mail
105 recipients token.user.mail
107 subject l(:mail_subject_lost_password)
106 subject l(:mail_subject_lost_password)
108 body :token => token,
107 body :token => token,
109 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
108 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
110 end
109 end
111
110
112 def register(token)
111 def register(token)
113 set_language_if_valid(token.user.language)
112 set_language_if_valid(token.user.language)
114 recipients token.user.mail
113 recipients token.user.mail
115 subject l(:mail_subject_register)
114 subject l(:mail_subject_register)
116 body :token => token,
115 body :token => token,
117 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
116 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
118 end
117 end
119
118
120 def test(user)
119 def test(user)
121 set_language_if_valid(user.language)
120 set_language_if_valid(user.language)
122 recipients user.mail
121 recipients user.mail
123 subject 'Redmine test'
122 subject 'Redmine test'
124 body :url => url_for(:controller => 'welcome')
123 body :url => url_for(:controller => 'welcome')
125 end
124 end
126
125
127 private
126 private
128 def initialize_defaults(method_name)
127 def initialize_defaults(method_name)
129 super
128 super
130 set_language_if_valid Setting.default_language
129 set_language_if_valid Setting.default_language
131 from Setting.mail_from
130 from Setting.mail_from
132 default_url_options[:host] = Setting.host_name
131 default_url_options[:host] = Setting.host_name
133 default_url_options[:protocol] = Setting.protocol
132 default_url_options[:protocol] = Setting.protocol
134 end
133 end
135
134
136 # Overrides the create_mail method
135 # Overrides the create_mail method
137 def create_mail
136 def create_mail
138 # Removes the current user from the recipients and cc
137 # Removes the current user from the recipients and cc
139 # if he doesn't want to receive notifications about what he does
138 # if he doesn't want to receive notifications about what he does
140 if User.current.pref[:no_self_notified]
139 if User.current.pref[:no_self_notified]
141 recipients.delete(User.current.mail) if recipients
140 recipients.delete(User.current.mail) if recipients
142 cc.delete(User.current.mail) if cc
141 cc.delete(User.current.mail) if cc
143 end
142 end
144 # Blind carbon copy recipients
143 # Blind carbon copy recipients
145 if Setting.bcc_recipients?
144 if Setting.bcc_recipients?
146 bcc([recipients, cc].flatten.compact.uniq)
145 bcc([recipients, cc].flatten.compact.uniq)
147 recipients []
146 recipients []
148 cc []
147 cc []
149 end
148 end
150 super
149 super
151 end
150 end
152
151
153 # Renders a message with the corresponding layout
152 # Renders a message with the corresponding layout
154 def render_message(method_name, body)
153 def render_message(method_name, body)
155 layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
154 layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
156 body[:content_for_layout] = render(:file => method_name, :body => body)
155 body[:content_for_layout] = render(:file => method_name, :body => body)
157 ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}")
156 ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}")
158 end
157 end
159
158
160 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
159 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
161 def self.controller_path
160 def self.controller_path
162 ''
161 ''
163 end unless respond_to?('controller_path')
162 end unless respond_to?('controller_path')
164 end
163 end
General Comments 0
You need to be logged in to leave comments. Login now