"""some hooks to handle notification on entity's changes:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"fromlogilab.common.textutilsimportnormalize_textfromcubicwebimportRegistryExceptionfromcubicweb.selectorsimportentity_implementsfromcubicweb.serverimporthookclassRenderAndSendNotificationView(hook.Operation):"""delay rendering of notification view until precommit"""defprecommit_event(self):view=self.viewifview.cw_rsetandself.session.deleted_in_transaction(view.cw_rset[cw_rset.cw_rowor0][cw_rset.cw_color0]):return# entity added and deleted in the same transactionself.view.render_and_send(**getattr(self,'viewargs',{}))classNotificationHook(hook.Hook):__abstract__=Truecategory='notification'defselect_view(self,vid,rset,row=0,col=0):returnself._cw.vreg['views'].select_or_none(vid,self._cw,rset=rset,row=0,col=0)classStatusChangeHook(NotificationHook):"""notify when a workflowable entity has its state modified"""__id__='notifystatuschange'__select__=NotificationHook.__select__&entity_implements('TrInfo')events=('after_add_entity',)def__call__(self):entity=self.entityifnotentity.from_state:# not a transitionreturnrset=entity.related('wf_info_for')view=self.select_view('notif_status_change',rset=rset,row=0)ifviewisNone:returncomment=entity.printable_value('comment',format='text/plain')ifcomment:comment=normalize_text(comment,80,rest=entity.comment_format=='text/rest')RenderAndSendNotificationView(self._cw,view=view,viewargs={'comment':comment,'previous_state':entity.previous_state.name,'current_state':entity.new_state.name})classRelationChangeHook(NotificationHook):__id__='notifyrelationchange'events=('before_add_relation','after_add_relation','before_delete_relation','after_delete_relation')def__call__(self):"""if a notification view is defined for the event, send notification email defined by the view """rset=self._cw.eid_rset(self.eidfrom)view=self.select_view('notif_%s_%s'%(self.event,self.rtype),rset=rset,row=0)ifviewisNone:returnRenderAndSendNotificationView(self._cw,view=view)classEntityChangeHook(NotificationHook):"""if a notification view is defined for the event, send notification email defined by the view """__id__='notifyentitychange'events=('after_add_entity','after_update_entity')def__call__(self):rset=self.entity.as_rset()view=self.select_view('notif_%s'%self.event,rset=rset,row=0)ifviewisNone:returnRenderAndSendNotificationView(self._cw,view=view)# supervising ##################################################################classSomethingChangedHook(NotificationHook):__id__='supervising'events=('before_add_relation','before_delete_relation','after_add_entity','before_update_entity')def__call__(self):dest=self._cw.vreg.config['supervising-addrs']ifnotdest:# no supervisors, don't do this for nothing...returnifself._call():SupervisionMailOp(self._cw)def_call(self):event=self.event.split('_',1)[1]ifevent=='update_entity':ifself._cw.added_in_transaction(self.entity.eid):returnFalseifself.entity.e_schema=='CWUser':ifnot(self.entity.edited_attributes-frozenset(('eid','modification_date','last_login_time'))):# don't record last_login_time update which are done# automatically at login timereturnFalseself._cw.transaction_data.setdefault('pendingchanges',[]).append((event,self))returnTrueclassEntityDeleteHook(SomethingChangedHook):__id__='supervisingentitydel'events=('before_delete_entity',)def_call(self):try:title=self.entity.dc_title()except:# may raise an error during deletion process, for instance due to# missing required relationtitle='#%s'%eidself._cw.transaction_data.setdefault('pendingchanges',[]).append(('delete_entity',(self.eid,str(self.entity.e_schema),title)))returnTrue