17 |
17 |
18 class SomethingChangedHook(Hook): |
18 class SomethingChangedHook(Hook): |
19 events = ('before_add_relation', 'before_delete_relation', |
19 events = ('before_add_relation', 'before_delete_relation', |
20 'after_add_entity', 'before_update_entity') |
20 'after_add_entity', 'before_update_entity') |
21 accepts = ('Any',) |
21 accepts = ('Any',) |
22 |
22 |
23 def call(self, session, *args): |
23 def call(self, session, *args): |
24 dest = self.config['supervising-addrs'] |
24 dest = self.config['supervising-addrs'] |
25 if not dest: # no supervisors, don't do this for nothing... |
25 if not dest: # no supervisors, don't do this for nothing... |
26 return |
26 return |
27 self.session = session |
27 self.session = session |
28 if self._call(*args): |
28 if self._call(*args): |
29 SupervisionMailOp(session) |
29 SupervisionMailOp(session) |
30 |
30 |
31 def _call(self, *args): |
31 def _call(self, *args): |
32 if self._event() == 'update_entity' and args[0].e_schema == 'CWUser': |
32 if self._event() == 'update_entity' and args[0].e_schema == 'CWUser': |
33 updated = set(args[0].iterkeys()) |
33 updated = set(args[0].iterkeys()) |
34 if not (updated - frozenset(('eid', 'modification_date', 'last_login_time'))): |
34 if not (updated - frozenset(('eid', 'modification_date', 'last_login_time'))): |
35 # don't record last_login_time update which are done |
35 # don't record last_login_time update which are done |
36 # automatically at login time |
36 # automatically at login time |
37 return False |
37 return False |
38 self.session.add_query_data('pendingchanges', (self._event(), args)) |
38 self.session.add_query_data('pendingchanges', (self._event(), args)) |
39 return True |
39 return True |
40 |
40 |
41 def _event(self): |
41 def _event(self): |
42 return self.event.split('_', 1)[1] |
42 return self.event.split('_', 1)[1] |
43 |
43 |
44 |
44 |
45 class EntityDeleteHook(SomethingChangedHook): |
45 class EntityDeleteHook(SomethingChangedHook): |
46 events = ('before_delete_entity',) |
46 events = ('before_delete_entity',) |
47 |
47 |
48 def _call(self, eid): |
48 def _call(self, eid): |
49 entity = self.session.entity(eid) |
49 entity = self.session.entity(eid) |
50 try: |
50 try: |
51 title = entity.dc_title() |
51 title = entity.dc_title() |
52 except: |
52 except: |
78 added.add(entity.eid) |
78 added.add(entity.eid) |
79 if entity.e_schema == 'TrInfo': |
79 if entity.e_schema == 'TrInfo': |
80 changes.remove(change) |
80 changes.remove(change) |
81 if entity.from_state: |
81 if entity.from_state: |
82 try: |
82 try: |
83 changes.remove( ('delete_relation', |
83 changes.remove( ('delete_relation', |
84 (entity.wf_info_for[0].eid, 'in_state', |
84 (entity.wf_info_for[0].eid, 'in_state', |
85 entity.from_state[0].eid)) ) |
85 entity.from_state[0].eid)) ) |
86 except ValueError: |
86 except ValueError: |
87 pass |
87 pass |
88 try: |
88 try: |
89 changes.remove( ('add_relation', |
89 changes.remove( ('add_relation', |
90 (entity.wf_info_for[0].eid, 'in_state', |
90 (entity.wf_info_for[0].eid, 'in_state', |
91 entity.to_state[0].eid)) ) |
91 entity.to_state[0].eid)) ) |
92 except ValueError: |
92 except ValueError: |
93 pass |
93 pass |
94 event = 'change_state' |
94 event = 'change_state' |
95 change = (event, |
95 change = (event, |
96 (entity.wf_info_for[0], |
96 (entity.wf_info_for[0], |
97 entity.from_state[0], entity.to_state[0])) |
97 entity.from_state[0], entity.to_state[0])) |
98 changes.append(change) |
98 changes.append(change) |
99 elif event == 'delete_entity': |
99 elif event == 'delete_entity': |
100 deleted.add(changedescr[0]) |
100 deleted.add(changedescr[0]) |
144 __select__ = none_rset() |
144 __select__ = none_rset() |
145 id = 'supervision_notif' |
145 id = 'supervision_notif' |
146 |
146 |
147 def recipients(self): |
147 def recipients(self): |
148 return self.config['supervising-addrs'] |
148 return self.config['supervising-addrs'] |
149 |
149 |
150 def subject(self): |
150 def subject(self): |
151 return self.req._('[%s supervision] changes summary') % self.config.appid |
151 return self.req._('[%s supervision] changes summary') % self.config.appid |
152 |
152 |
153 def call(self, changes): |
153 def call(self, changes): |
154 user = self.req.actual_session().user |
154 user = self.req.actual_session().user |
155 self.w(self.req._('user %s has made the following change(s):\n\n') |
155 self.w(self.req._('user %s has made the following change(s):\n\n') |
156 % user.login) |
156 % user.login) |
157 for event, changedescr in filter_changes(changes): |
157 for event, changedescr in filter_changes(changes): |
161 |
161 |
162 def _entity_context(self, entity): |
162 def _entity_context(self, entity): |
163 return {'eid': entity.eid, |
163 return {'eid': entity.eid, |
164 'etype': entity.dc_type().lower(), |
164 'etype': entity.dc_type().lower(), |
165 'title': entity.dc_title()} |
165 'title': entity.dc_title()} |
166 |
166 |
167 def add_entity(self, entity): |
167 def add_entity(self, entity): |
168 msg = self.req._('added %(etype)s #%(eid)s (%(title)s)') |
168 msg = self.req._('added %(etype)s #%(eid)s (%(title)s)') |
169 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
169 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
170 self.w(u' %s' % entity.absolute_url()) |
170 self.w(u' %s' % entity.absolute_url()) |
171 |
171 |
172 def update_entity(self, entity): |
172 def update_entity(self, entity): |
173 msg = self.req._('updated %(etype)s #%(eid)s (%(title)s)') |
173 msg = self.req._('updated %(etype)s #%(eid)s (%(title)s)') |
174 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
174 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
175 # XXX print changes |
175 # XXX print changes |
176 self.w(u' %s' % entity.absolute_url()) |
176 self.w(u' %s' % entity.absolute_url()) |
177 |
177 |
178 def delete_entity(self, eid, etype, title): |
178 def delete_entity(self, eid, etype, title): |
179 msg = self.req._('deleted %(etype)s #%(eid)s (%(title)s)') |
179 msg = self.req._('deleted %(etype)s #%(eid)s (%(title)s)') |
180 etype = display_name(self.req, etype).lower() |
180 etype = display_name(self.req, etype).lower() |
181 self.w(msg % locals()) |
181 self.w(msg % locals()) |
182 |
182 |
183 def change_state(self, entity, fromstate, tostate): |
183 def change_state(self, entity, fromstate, tostate): |
184 msg = self.req._('changed state of %(etype)s #%(eid)s (%(title)s)') |
184 msg = self.req._('changed state of %(etype)s #%(eid)s (%(title)s)') |
185 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
185 self.w(u'%s\n' % (msg % self._entity_context(entity))) |
186 self.w(_(' from state %(fromstate)s to state %(tostate)s\n' % |
186 self.w(_(' from state %(fromstate)s to state %(tostate)s\n' % |
187 {'fromstate': _(fromstate.name), 'tostate': _(tostate.name)})) |
187 {'fromstate': _(fromstate.name), 'tostate': _(tostate.name)})) |
188 self.w(u' %s' % entity.absolute_url()) |
188 self.w(u' %s' % entity.absolute_url()) |
189 |
189 |
190 def _relation_context(self, fromeid, rtype, toeid): |
190 def _relation_context(self, fromeid, rtype, toeid): |
191 _ = self.req._ |
191 _ = self.req._ |
192 session = self.req.actual_session() |
192 session = self.req.actual_session() |
193 def describe(eid): |
193 def describe(eid): |
194 try: |
194 try: |
200 return {'rtype': _(rtype), |
200 return {'rtype': _(rtype), |
201 'fromeid': fromeid, |
201 'fromeid': fromeid, |
202 'frometype': describe(fromeid), |
202 'frometype': describe(fromeid), |
203 'toeid': toeid, |
203 'toeid': toeid, |
204 'toetype': describe(toeid)} |
204 'toetype': describe(toeid)} |
205 |
205 |
206 def add_relation(self, fromeid, rtype, toeid): |
206 def add_relation(self, fromeid, rtype, toeid): |
207 msg = self.req._('added relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s') |
207 msg = self.req._('added relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s') |
208 self.w(msg % self._relation_context(fromeid, rtype, toeid)) |
208 self.w(msg % self._relation_context(fromeid, rtype, toeid)) |
209 |
209 |
210 def delete_relation(self, fromeid, rtype, toeid): |
210 def delete_relation(self, fromeid, rtype, toeid): |
211 msg = self.req._('deleted relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s') |
211 msg = self.req._('deleted relation %(rtype)s from %(frometype)s #%(fromeid)s to %(toetype)s #%(toeid)s') |
212 self.w(msg % self._relation_context(fromeid, rtype, toeid)) |
212 self.w(msg % self._relation_context(fromeid, rtype, toeid)) |
213 |
213 |
214 |
214 |
215 class SupervisionMailOp(SendMailOp): |
215 class SupervisionMailOp(SendMailOp): |
216 """special send email operation which should be done only once for a bunch |
216 """special send email operation which should be done only once for a bunch |
217 of changes |
217 of changes |
218 """ |
218 """ |
219 def _get_view(self): |
219 def _get_view(self): |
220 return self.session.vreg.select_component('supervision_notif', |
220 return self.session.vreg.select_component('supervision_notif', |
221 self.session, None) |
221 self.session, None) |
222 |
222 |
223 def _prepare_email(self): |
223 def _prepare_email(self): |
224 session = self.session |
224 session = self.session |
225 config = session.vreg.config |
225 config = session.vreg.config |
226 uinfo = {'email': config['sender-addr'], |
226 uinfo = {'email': config['sender-addr'], |
227 'name': config['sender-name']} |
227 'name': config['sender-name']} |
228 view = self._get_view() |
228 view = self._get_view() |
229 content = view.dispatch(changes=session.query_data('pendingchanges')) |
229 content = view.render(changes=session.query_data('pendingchanges')) |
230 recipients = view.recipients() |
230 recipients = view.recipients() |
231 msg = format_mail(uinfo, recipients, content, view.subject(), config=config) |
231 msg = format_mail(uinfo, recipients, content, view.subject(), config=config) |
232 self.to_send = [(msg, recipients)] |
232 self.to_send = [(msg, recipients)] |
233 |
233 |
234 def commit_event(self): |
234 def commit_event(self): |