##// END OF EJS Templates
notifications: added update PR case.
marcink -
r4137:754144f0 default
parent child Browse files
Show More
@@ -1,390 +1,394 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
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 Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 """
22 """
23 Model for notifications
23 Model for notifications
24 """
24 """
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from pyramid.threadlocal import get_current_request
29 from pyramid.threadlocal import get_current_request
30 from sqlalchemy.sql.expression import false, true
30 from sqlalchemy.sql.expression import false, true
31
31
32 import rhodecode
32 import rhodecode
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import Notification, User, UserNotification
35 from rhodecode.model.db import Notification, User, UserNotification
36 from rhodecode.model.meta import Session
36 from rhodecode.model.meta import Session
37 from rhodecode.translation import TranslationString
37 from rhodecode.translation import TranslationString
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41
41
42 class NotificationModel(BaseModel):
42 class NotificationModel(BaseModel):
43
43
44 cls = Notification
44 cls = Notification
45
45
46 def __get_notification(self, notification):
46 def __get_notification(self, notification):
47 if isinstance(notification, Notification):
47 if isinstance(notification, Notification):
48 return notification
48 return notification
49 elif isinstance(notification, (int, long)):
49 elif isinstance(notification, (int, long)):
50 return Notification.get(notification)
50 return Notification.get(notification)
51 else:
51 else:
52 if notification:
52 if notification:
53 raise Exception('notification must be int, long or Instance'
53 raise Exception('notification must be int, long or Instance'
54 ' of Notification got %s' % type(notification))
54 ' of Notification got %s' % type(notification))
55
55
56 def create(
56 def create(
57 self, created_by, notification_subject, notification_body,
57 self, created_by, notification_subject, notification_body,
58 notification_type=Notification.TYPE_MESSAGE, recipients=None,
58 notification_type=Notification.TYPE_MESSAGE, recipients=None,
59 mention_recipients=None, with_email=True, email_kwargs=None):
59 mention_recipients=None, with_email=True, email_kwargs=None):
60 """
60 """
61
61
62 Creates notification of given type
62 Creates notification of given type
63
63
64 :param created_by: int, str or User instance. User who created this
64 :param created_by: int, str or User instance. User who created this
65 notification
65 notification
66 :param notification_subject: subject of notification itself
66 :param notification_subject: subject of notification itself
67 :param notification_body: body of notification text
67 :param notification_body: body of notification text
68 :param notification_type: type of notification, based on that we
68 :param notification_type: type of notification, based on that we
69 pick templates
69 pick templates
70
70
71 :param recipients: list of int, str or User objects, when None
71 :param recipients: list of int, str or User objects, when None
72 is given send to all admins
72 is given send to all admins
73 :param mention_recipients: list of int, str or User objects,
73 :param mention_recipients: list of int, str or User objects,
74 that were mentioned
74 that were mentioned
75 :param with_email: send email with this notification
75 :param with_email: send email with this notification
76 :param email_kwargs: dict with arguments to generate email
76 :param email_kwargs: dict with arguments to generate email
77 """
77 """
78
78
79 from rhodecode.lib.celerylib import tasks, run_task
79 from rhodecode.lib.celerylib import tasks, run_task
80
80
81 if recipients and not getattr(recipients, '__iter__', False):
81 if recipients and not getattr(recipients, '__iter__', False):
82 raise Exception('recipients must be an iterable object')
82 raise Exception('recipients must be an iterable object')
83
83
84 created_by_obj = self._get_user(created_by)
84 created_by_obj = self._get_user(created_by)
85 # default MAIN body if not given
85 # default MAIN body if not given
86 email_kwargs = email_kwargs or {'body': notification_body}
86 email_kwargs = email_kwargs or {'body': notification_body}
87 mention_recipients = mention_recipients or set()
87 mention_recipients = mention_recipients or set()
88
88
89 if not created_by_obj:
89 if not created_by_obj:
90 raise Exception('unknown user %s' % created_by)
90 raise Exception('unknown user %s' % created_by)
91
91
92 if recipients is None:
92 if recipients is None:
93 # recipients is None means to all admins
93 # recipients is None means to all admins
94 recipients_objs = User.query().filter(User.admin == true()).all()
94 recipients_objs = User.query().filter(User.admin == true()).all()
95 log.debug('sending notifications %s to admins: %s',
95 log.debug('sending notifications %s to admins: %s',
96 notification_type, recipients_objs)
96 notification_type, recipients_objs)
97 else:
97 else:
98 recipients_objs = set()
98 recipients_objs = set()
99 for u in recipients:
99 for u in recipients:
100 obj = self._get_user(u)
100 obj = self._get_user(u)
101 if obj:
101 if obj:
102 recipients_objs.add(obj)
102 recipients_objs.add(obj)
103 else: # we didn't find this user, log the error and carry on
103 else: # we didn't find this user, log the error and carry on
104 log.error('cannot notify unknown user %r', u)
104 log.error('cannot notify unknown user %r', u)
105
105
106 if not recipients_objs:
106 if not recipients_objs:
107 raise Exception('no valid recipients specified')
107 raise Exception('no valid recipients specified')
108
108
109 log.debug('sending notifications %s to %s',
109 log.debug('sending notifications %s to %s',
110 notification_type, recipients_objs)
110 notification_type, recipients_objs)
111
111
112 # add mentioned users into recipients
112 # add mentioned users into recipients
113 final_recipients = set(recipients_objs).union(mention_recipients)
113 final_recipients = set(recipients_objs).union(mention_recipients)
114
114
115 notification = Notification.create(
115 notification = Notification.create(
116 created_by=created_by_obj, subject=notification_subject,
116 created_by=created_by_obj, subject=notification_subject,
117 body=notification_body, recipients=final_recipients,
117 body=notification_body, recipients=final_recipients,
118 type_=notification_type
118 type_=notification_type
119 )
119 )
120
120
121 if not with_email: # skip sending email, and just create notification
121 if not with_email: # skip sending email, and just create notification
122 return notification
122 return notification
123
123
124 # don't send email to person who created this comment
124 # don't send email to person who created this comment
125 rec_objs = set(recipients_objs).difference({created_by_obj})
125 rec_objs = set(recipients_objs).difference({created_by_obj})
126
126
127 # now notify all recipients in question
127 # now notify all recipients in question
128
128
129 for recipient in rec_objs.union(mention_recipients):
129 for recipient in rec_objs.union(mention_recipients):
130 # inject current recipient
130 # inject current recipient
131 email_kwargs['recipient'] = recipient
131 email_kwargs['recipient'] = recipient
132 email_kwargs['mention'] = recipient in mention_recipients
132 email_kwargs['mention'] = recipient in mention_recipients
133 (subject, headers, email_body,
133 (subject, headers, email_body,
134 email_body_plaintext) = EmailNotificationModel().render_email(
134 email_body_plaintext) = EmailNotificationModel().render_email(
135 notification_type, **email_kwargs)
135 notification_type, **email_kwargs)
136
136
137 log.debug(
137 log.debug(
138 'Creating notification email task for user:`%s`', recipient)
138 'Creating notification email task for user:`%s`', recipient)
139 task = run_task(
139 task = run_task(
140 tasks.send_email, recipient.email, subject,
140 tasks.send_email, recipient.email, subject,
141 email_body_plaintext, email_body)
141 email_body_plaintext, email_body)
142 log.debug('Created email task: %s', task)
142 log.debug('Created email task: %s', task)
143
143
144 return notification
144 return notification
145
145
146 def delete(self, user, notification):
146 def delete(self, user, notification):
147 # we don't want to remove actual notification just the assignment
147 # we don't want to remove actual notification just the assignment
148 try:
148 try:
149 notification = self.__get_notification(notification)
149 notification = self.__get_notification(notification)
150 user = self._get_user(user)
150 user = self._get_user(user)
151 if notification and user:
151 if notification and user:
152 obj = UserNotification.query()\
152 obj = UserNotification.query()\
153 .filter(UserNotification.user == user)\
153 .filter(UserNotification.user == user)\
154 .filter(UserNotification.notification == notification)\
154 .filter(UserNotification.notification == notification)\
155 .one()
155 .one()
156 Session().delete(obj)
156 Session().delete(obj)
157 return True
157 return True
158 except Exception:
158 except Exception:
159 log.error(traceback.format_exc())
159 log.error(traceback.format_exc())
160 raise
160 raise
161
161
162 def get_for_user(self, user, filter_=None):
162 def get_for_user(self, user, filter_=None):
163 """
163 """
164 Get mentions for given user, filter them if filter dict is given
164 Get mentions for given user, filter them if filter dict is given
165 """
165 """
166 user = self._get_user(user)
166 user = self._get_user(user)
167
167
168 q = UserNotification.query()\
168 q = UserNotification.query()\
169 .filter(UserNotification.user == user)\
169 .filter(UserNotification.user == user)\
170 .join((
170 .join((
171 Notification, UserNotification.notification_id ==
171 Notification, UserNotification.notification_id ==
172 Notification.notification_id))
172 Notification.notification_id))
173 if filter_ == ['all']:
173 if filter_ == ['all']:
174 q = q # no filter
174 q = q # no filter
175 elif filter_ == ['unread']:
175 elif filter_ == ['unread']:
176 q = q.filter(UserNotification.read == false())
176 q = q.filter(UserNotification.read == false())
177 elif filter_:
177 elif filter_:
178 q = q.filter(Notification.type_.in_(filter_))
178 q = q.filter(Notification.type_.in_(filter_))
179
179
180 return q
180 return q
181
181
182 def mark_read(self, user, notification):
182 def mark_read(self, user, notification):
183 try:
183 try:
184 notification = self.__get_notification(notification)
184 notification = self.__get_notification(notification)
185 user = self._get_user(user)
185 user = self._get_user(user)
186 if notification and user:
186 if notification and user:
187 obj = UserNotification.query()\
187 obj = UserNotification.query()\
188 .filter(UserNotification.user == user)\
188 .filter(UserNotification.user == user)\
189 .filter(UserNotification.notification == notification)\
189 .filter(UserNotification.notification == notification)\
190 .one()
190 .one()
191 obj.read = True
191 obj.read = True
192 Session().add(obj)
192 Session().add(obj)
193 return True
193 return True
194 except Exception:
194 except Exception:
195 log.error(traceback.format_exc())
195 log.error(traceback.format_exc())
196 raise
196 raise
197
197
198 def mark_all_read_for_user(self, user, filter_=None):
198 def mark_all_read_for_user(self, user, filter_=None):
199 user = self._get_user(user)
199 user = self._get_user(user)
200 q = UserNotification.query()\
200 q = UserNotification.query()\
201 .filter(UserNotification.user == user)\
201 .filter(UserNotification.user == user)\
202 .filter(UserNotification.read == false())\
202 .filter(UserNotification.read == false())\
203 .join((
203 .join((
204 Notification, UserNotification.notification_id ==
204 Notification, UserNotification.notification_id ==
205 Notification.notification_id))
205 Notification.notification_id))
206 if filter_ == ['unread']:
206 if filter_ == ['unread']:
207 q = q.filter(UserNotification.read == false())
207 q = q.filter(UserNotification.read == false())
208 elif filter_:
208 elif filter_:
209 q = q.filter(Notification.type_.in_(filter_))
209 q = q.filter(Notification.type_.in_(filter_))
210
210
211 # this is a little inefficient but sqlalchemy doesn't support
211 # this is a little inefficient but sqlalchemy doesn't support
212 # update on joined tables :(
212 # update on joined tables :(
213 for obj in q.all():
213 for obj in q.all():
214 obj.read = True
214 obj.read = True
215 Session().add(obj)
215 Session().add(obj)
216
216
217 def get_unread_cnt_for_user(self, user):
217 def get_unread_cnt_for_user(self, user):
218 user = self._get_user(user)
218 user = self._get_user(user)
219 return UserNotification.query()\
219 return UserNotification.query()\
220 .filter(UserNotification.read == false())\
220 .filter(UserNotification.read == false())\
221 .filter(UserNotification.user == user).count()
221 .filter(UserNotification.user == user).count()
222
222
223 def get_unread_for_user(self, user):
223 def get_unread_for_user(self, user):
224 user = self._get_user(user)
224 user = self._get_user(user)
225 return [x.notification for x in UserNotification.query()
225 return [x.notification for x in UserNotification.query()
226 .filter(UserNotification.read == false())
226 .filter(UserNotification.read == false())
227 .filter(UserNotification.user == user).all()]
227 .filter(UserNotification.user == user).all()]
228
228
229 def get_user_notification(self, user, notification):
229 def get_user_notification(self, user, notification):
230 user = self._get_user(user)
230 user = self._get_user(user)
231 notification = self.__get_notification(notification)
231 notification = self.__get_notification(notification)
232
232
233 return UserNotification.query()\
233 return UserNotification.query()\
234 .filter(UserNotification.notification == notification)\
234 .filter(UserNotification.notification == notification)\
235 .filter(UserNotification.user == user).scalar()
235 .filter(UserNotification.user == user).scalar()
236
236
237 def make_description(self, notification, translate, show_age=True):
237 def make_description(self, notification, translate, show_age=True):
238 """
238 """
239 Creates a human readable description based on properties
239 Creates a human readable description based on properties
240 of notification object
240 of notification object
241 """
241 """
242 _ = translate
242 _ = translate
243 _map = {
243 _map = {
244 notification.TYPE_CHANGESET_COMMENT: [
244 notification.TYPE_CHANGESET_COMMENT: [
245 _('%(user)s commented on commit %(date_or_age)s'),
245 _('%(user)s commented on commit %(date_or_age)s'),
246 _('%(user)s commented on commit at %(date_or_age)s'),
246 _('%(user)s commented on commit at %(date_or_age)s'),
247 ],
247 ],
248 notification.TYPE_MESSAGE: [
248 notification.TYPE_MESSAGE: [
249 _('%(user)s sent message %(date_or_age)s'),
249 _('%(user)s sent message %(date_or_age)s'),
250 _('%(user)s sent message at %(date_or_age)s'),
250 _('%(user)s sent message at %(date_or_age)s'),
251 ],
251 ],
252 notification.TYPE_MENTION: [
252 notification.TYPE_MENTION: [
253 _('%(user)s mentioned you %(date_or_age)s'),
253 _('%(user)s mentioned you %(date_or_age)s'),
254 _('%(user)s mentioned you at %(date_or_age)s'),
254 _('%(user)s mentioned you at %(date_or_age)s'),
255 ],
255 ],
256 notification.TYPE_REGISTRATION: [
256 notification.TYPE_REGISTRATION: [
257 _('%(user)s registered in RhodeCode %(date_or_age)s'),
257 _('%(user)s registered in RhodeCode %(date_or_age)s'),
258 _('%(user)s registered in RhodeCode at %(date_or_age)s'),
258 _('%(user)s registered in RhodeCode at %(date_or_age)s'),
259 ],
259 ],
260 notification.TYPE_PULL_REQUEST: [
260 notification.TYPE_PULL_REQUEST: [
261 _('%(user)s opened new pull request %(date_or_age)s'),
261 _('%(user)s opened new pull request %(date_or_age)s'),
262 _('%(user)s opened new pull request at %(date_or_age)s'),
262 _('%(user)s opened new pull request at %(date_or_age)s'),
263 ],
263 ],
264 notification.TYPE_PULL_REQUEST_UPDATE: [
265 _('%(user)s updated pull request %(date_or_age)s'),
266 _('%(user)s updated pull request at %(date_or_age)s'),
267 ],
264 notification.TYPE_PULL_REQUEST_COMMENT: [
268 notification.TYPE_PULL_REQUEST_COMMENT: [
265 _('%(user)s commented on pull request %(date_or_age)s'),
269 _('%(user)s commented on pull request %(date_or_age)s'),
266 _('%(user)s commented on pull request at %(date_or_age)s'),
270 _('%(user)s commented on pull request at %(date_or_age)s'),
267 ],
271 ],
268 }
272 }
269
273
270 templates = _map[notification.type_]
274 templates = _map[notification.type_]
271
275
272 if show_age:
276 if show_age:
273 template = templates[0]
277 template = templates[0]
274 date_or_age = h.age(notification.created_on)
278 date_or_age = h.age(notification.created_on)
275 if translate:
279 if translate:
276 date_or_age = translate(date_or_age)
280 date_or_age = translate(date_or_age)
277
281
278 if isinstance(date_or_age, TranslationString):
282 if isinstance(date_or_age, TranslationString):
279 date_or_age = date_or_age.interpolate()
283 date_or_age = date_or_age.interpolate()
280
284
281 else:
285 else:
282 template = templates[1]
286 template = templates[1]
283 date_or_age = h.format_date(notification.created_on)
287 date_or_age = h.format_date(notification.created_on)
284
288
285 return template % {
289 return template % {
286 'user': notification.created_by_user.username,
290 'user': notification.created_by_user.username,
287 'date_or_age': date_or_age,
291 'date_or_age': date_or_age,
288 }
292 }
289
293
290
294
291 class EmailNotificationModel(BaseModel):
295 class EmailNotificationModel(BaseModel):
292 TYPE_COMMIT_COMMENT = Notification.TYPE_CHANGESET_COMMENT
296 TYPE_COMMIT_COMMENT = Notification.TYPE_CHANGESET_COMMENT
293 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
297 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
294 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
298 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
295 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
299 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
296 TYPE_PULL_REQUEST_UPDATE = Notification.TYPE_PULL_REQUEST_UPDATE
300 TYPE_PULL_REQUEST_UPDATE = Notification.TYPE_PULL_REQUEST_UPDATE
297 TYPE_MAIN = Notification.TYPE_MESSAGE
301 TYPE_MAIN = Notification.TYPE_MESSAGE
298
302
299 TYPE_PASSWORD_RESET = 'password_reset'
303 TYPE_PASSWORD_RESET = 'password_reset'
300 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
304 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
301 TYPE_EMAIL_TEST = 'email_test'
305 TYPE_EMAIL_TEST = 'email_test'
302 TYPE_TEST = 'test'
306 TYPE_TEST = 'test'
303
307
304 email_types = {
308 email_types = {
305 TYPE_MAIN:
309 TYPE_MAIN:
306 'rhodecode:templates/email_templates/main.mako',
310 'rhodecode:templates/email_templates/main.mako',
307 TYPE_TEST:
311 TYPE_TEST:
308 'rhodecode:templates/email_templates/test.mako',
312 'rhodecode:templates/email_templates/test.mako',
309 TYPE_EMAIL_TEST:
313 TYPE_EMAIL_TEST:
310 'rhodecode:templates/email_templates/email_test.mako',
314 'rhodecode:templates/email_templates/email_test.mako',
311 TYPE_REGISTRATION:
315 TYPE_REGISTRATION:
312 'rhodecode:templates/email_templates/user_registration.mako',
316 'rhodecode:templates/email_templates/user_registration.mako',
313 TYPE_PASSWORD_RESET:
317 TYPE_PASSWORD_RESET:
314 'rhodecode:templates/email_templates/password_reset.mako',
318 'rhodecode:templates/email_templates/password_reset.mako',
315 TYPE_PASSWORD_RESET_CONFIRMATION:
319 TYPE_PASSWORD_RESET_CONFIRMATION:
316 'rhodecode:templates/email_templates/password_reset_confirmation.mako',
320 'rhodecode:templates/email_templates/password_reset_confirmation.mako',
317 TYPE_COMMIT_COMMENT:
321 TYPE_COMMIT_COMMENT:
318 'rhodecode:templates/email_templates/commit_comment.mako',
322 'rhodecode:templates/email_templates/commit_comment.mako',
319 TYPE_PULL_REQUEST:
323 TYPE_PULL_REQUEST:
320 'rhodecode:templates/email_templates/pull_request_review.mako',
324 'rhodecode:templates/email_templates/pull_request_review.mako',
321 TYPE_PULL_REQUEST_COMMENT:
325 TYPE_PULL_REQUEST_COMMENT:
322 'rhodecode:templates/email_templates/pull_request_comment.mako',
326 'rhodecode:templates/email_templates/pull_request_comment.mako',
323 TYPE_PULL_REQUEST_UPDATE:
327 TYPE_PULL_REQUEST_UPDATE:
324 'rhodecode:templates/email_templates/pull_request_update.mako',
328 'rhodecode:templates/email_templates/pull_request_update.mako',
325 }
329 }
326
330
327 def __init__(self):
331 def __init__(self):
328 """
332 """
329 Example usage::
333 Example usage::
330
334
331 (subject, headers, email_body,
335 (subject, headers, email_body,
332 email_body_plaintext) = EmailNotificationModel().render_email(
336 email_body_plaintext) = EmailNotificationModel().render_email(
333 EmailNotificationModel.TYPE_TEST, **email_kwargs)
337 EmailNotificationModel.TYPE_TEST, **email_kwargs)
334
338
335 """
339 """
336 super(EmailNotificationModel, self).__init__()
340 super(EmailNotificationModel, self).__init__()
337 self.rhodecode_instance_name = rhodecode.CONFIG.get('rhodecode_title')
341 self.rhodecode_instance_name = rhodecode.CONFIG.get('rhodecode_title')
338
342
339 def _update_kwargs_for_render(self, kwargs):
343 def _update_kwargs_for_render(self, kwargs):
340 """
344 """
341 Inject params required for Mako rendering
345 Inject params required for Mako rendering
342
346
343 :param kwargs:
347 :param kwargs:
344 """
348 """
345
349
346 kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name
350 kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name
347 kwargs['rhodecode_version'] = rhodecode.__version__
351 kwargs['rhodecode_version'] = rhodecode.__version__
348 instance_url = h.route_url('home')
352 instance_url = h.route_url('home')
349 _kwargs = {
353 _kwargs = {
350 'instance_url': instance_url,
354 'instance_url': instance_url,
351 'whitespace_filter': self.whitespace_filter
355 'whitespace_filter': self.whitespace_filter
352 }
356 }
353 _kwargs.update(kwargs)
357 _kwargs.update(kwargs)
354 return _kwargs
358 return _kwargs
355
359
356 def whitespace_filter(self, text):
360 def whitespace_filter(self, text):
357 return text.replace('\n', '').replace('\t', '')
361 return text.replace('\n', '').replace('\t', '')
358
362
359 def get_renderer(self, type_, request):
363 def get_renderer(self, type_, request):
360 template_name = self.email_types[type_]
364 template_name = self.email_types[type_]
361 return request.get_partial_renderer(template_name)
365 return request.get_partial_renderer(template_name)
362
366
363 def render_email(self, type_, **kwargs):
367 def render_email(self, type_, **kwargs):
364 """
368 """
365 renders template for email, and returns a tuple of
369 renders template for email, and returns a tuple of
366 (subject, email_headers, email_html_body, email_plaintext_body)
370 (subject, email_headers, email_html_body, email_plaintext_body)
367 """
371 """
368 # translator and helpers inject
372 # translator and helpers inject
369 _kwargs = self._update_kwargs_for_render(kwargs)
373 _kwargs = self._update_kwargs_for_render(kwargs)
370 request = get_current_request()
374 request = get_current_request()
371 email_template = self.get_renderer(type_, request=request)
375 email_template = self.get_renderer(type_, request=request)
372
376
373 subject = email_template.render('subject', **_kwargs)
377 subject = email_template.render('subject', **_kwargs)
374
378
375 try:
379 try:
376 headers = email_template.render('headers', **_kwargs)
380 headers = email_template.render('headers', **_kwargs)
377 except AttributeError:
381 except AttributeError:
378 # it's not defined in template, ok we can skip it
382 # it's not defined in template, ok we can skip it
379 headers = ''
383 headers = ''
380
384
381 try:
385 try:
382 body_plaintext = email_template.render('body_plaintext', **_kwargs)
386 body_plaintext = email_template.render('body_plaintext', **_kwargs)
383 except AttributeError:
387 except AttributeError:
384 # it's not defined in template, ok we can skip it
388 # it's not defined in template, ok we can skip it
385 body_plaintext = ''
389 body_plaintext = ''
386
390
387 # render WHOLE template
391 # render WHOLE template
388 body = email_template.render(None, **_kwargs)
392 body = email_template.render(None, **_kwargs)
389
393
390 return subject, headers, body, body_plaintext
394 return subject, headers, body, body_plaintext
General Comments 0
You need to be logged in to leave comments. Login now