equal
deleted
inserted
replaced
20 """ |
20 """ |
21 __docformat__ = "restructuredtext en" |
21 __docformat__ = "restructuredtext en" |
22 |
22 |
23 from logilab.common.textutils import normalize_text |
23 from logilab.common.textutils import normalize_text |
24 |
24 |
|
25 from cubicweb import RegistryNotFound |
25 from cubicweb.selectors import is_instance |
26 from cubicweb.selectors import is_instance |
26 from cubicweb.server import hook |
27 from cubicweb.server import hook |
27 from cubicweb.sobjects.supervising import SupervisionMailOp |
28 from cubicweb.sobjects.supervising import SupervisionMailOp |
28 |
29 |
29 class RenderAndSendNotificationView(hook.Operation): |
30 class RenderAndSendNotificationView(hook.Operation): |
40 class NotificationHook(hook.Hook): |
41 class NotificationHook(hook.Hook): |
41 __abstract__ = True |
42 __abstract__ = True |
42 category = 'notification' |
43 category = 'notification' |
43 |
44 |
44 def select_view(self, vid, rset, row=0, col=0): |
45 def select_view(self, vid, rset, row=0, col=0): |
45 return self._cw.vreg['views'].select_or_none(vid, self._cw, rset=rset, |
46 try: |
46 row=row, col=col) |
47 return self._cw.vreg['views'].select_or_none(vid, self._cw, rset=rset, |
|
48 row=row, col=col) |
|
49 except RegistryNotFound: # can happen in some config |
|
50 # (e.g. repo only config with no |
|
51 # notification views registered by |
|
52 # the instance's cubes) |
|
53 return None |
47 |
54 |
48 |
55 |
49 class StatusChangeHook(NotificationHook): |
56 class StatusChangeHook(NotificationHook): |
50 """notify when a workflowable entity has its state modified""" |
57 """notify when a workflowable entity has its state modified""" |
51 __regid__ = 'notifystatuschange' |
58 __regid__ = 'notifystatuschange' |
67 comment = normalize_text(comment, 80) |
74 comment = normalize_text(comment, 80) |
68 RenderAndSendNotificationView(self._cw, view=view, viewargs={ |
75 RenderAndSendNotificationView(self._cw, view=view, viewargs={ |
69 'comment': comment, 'previous_state': entity.previous_state.name, |
76 'comment': comment, 'previous_state': entity.previous_state.name, |
70 'current_state': entity.new_state.name}) |
77 'current_state': entity.new_state.name}) |
71 |
78 |
72 |
|
73 class RelationChangeHook(NotificationHook): |
79 class RelationChangeHook(NotificationHook): |
74 __regid__ = 'notifyrelationchange' |
80 __regid__ = 'notifyrelationchange' |
75 events = ('before_add_relation', 'after_add_relation', |
81 events = ('before_add_relation', 'after_add_relation', |
76 'before_delete_relation', 'after_delete_relation') |
82 'before_delete_relation', 'after_delete_relation') |
77 |
83 |
123 def __call__(self): |
129 def __call__(self): |
124 session = self._cw |
130 session = self._cw |
125 if session.added_in_transaction(self.entity.eid): |
131 if session.added_in_transaction(self.entity.eid): |
126 return # entity is being created |
132 return # entity is being created |
127 # then compute changes |
133 # then compute changes |
128 attrs = [k for k in self.entity.edited_attributes |
134 attrs = [k for k in self.entity.cw_edited |
129 if not k in self.skip_attrs] |
135 if not k in self.skip_attrs] |
130 if not attrs: |
136 if not attrs: |
131 return |
137 return |
132 changes = session.transaction_data.setdefault('changes', {}) |
138 changes = session.transaction_data.setdefault('changes', {}) |
133 thisentitychanges = changes.setdefault(self.entity.eid, set()) |
139 thisentitychanges = changes.setdefault(self.entity.eid, set()) |
138 rqlrestr.append('X %s %s' % (attr, var)) |
144 rqlrestr.append('X %s %s' % (attr, var)) |
139 rql = 'Any %s WHERE %s' % (','.join(rqlsel), ','.join(rqlrestr)) |
145 rql = 'Any %s WHERE %s' % (','.join(rqlsel), ','.join(rqlrestr)) |
140 rset = session.execute(rql, {'x': self.entity.eid}) |
146 rset = session.execute(rql, {'x': self.entity.eid}) |
141 for i, attr in enumerate(attrs): |
147 for i, attr in enumerate(attrs): |
142 oldvalue = rset[0][i] |
148 oldvalue = rset[0][i] |
143 newvalue = self.entity[attr] |
149 newvalue = self.entity.cw_edited[attr] |
144 if oldvalue != newvalue: |
150 if oldvalue != newvalue: |
145 thisentitychanges.add((attr, oldvalue, newvalue)) |
151 thisentitychanges.add((attr, oldvalue, newvalue)) |
146 if thisentitychanges: |
152 if thisentitychanges: |
147 EntityUpdatedNotificationOp(session) |
153 EntityUpdatedNotificationOp(session) |
148 |
154 |
166 event = self.event.split('_', 1)[1] |
172 event = self.event.split('_', 1)[1] |
167 if event == 'update_entity': |
173 if event == 'update_entity': |
168 if self._cw.added_in_transaction(self.entity.eid): |
174 if self._cw.added_in_transaction(self.entity.eid): |
169 return False |
175 return False |
170 if self.entity.e_schema == 'CWUser': |
176 if self.entity.e_schema == 'CWUser': |
171 if not (self.entity.edited_attributes - frozenset(('eid', 'modification_date', |
177 if not (frozenset(self.entity.cw_edited) |
172 'last_login_time'))): |
178 - frozenset(('eid', 'modification_date', |
|
179 'last_login_time'))): |
173 # don't record last_login_time update which are done |
180 # don't record last_login_time update which are done |
174 # automatically at login time |
181 # automatically at login time |
175 return False |
182 return False |
176 self._cw.transaction_data.setdefault('pendingchanges', []).append( |
183 self._cw.transaction_data.setdefault('pendingchanges', []).append( |
177 (event, self)) |
184 (event, self)) |