server/hooks.py
branch3.5
changeset 2949 a2aa2c51f3be
parent 2920 64322aa83a1d
child 2978 d8c5ad14ab8e
equal deleted inserted replaced
2948:d3cd8bd20ee5 2949:a2aa2c51f3be
   415     hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group')
   415     hm.register_hook(after_add_in_group, 'after_add_relation', 'in_group')
   416     hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group')
   416     hm.register_hook(after_del_in_group, 'after_delete_relation', 'in_group')
   417 
   417 
   418 
   418 
   419 # workflow handling ###########################################################
   419 # workflow handling ###########################################################
       
   420 
       
   421 def _change_state(session, x, oldstate, newstate):
       
   422     nocheck = session.transaction_data.setdefault('skip-security', set())
       
   423     nocheck.add((x, 'in_state', oldstate))
       
   424     nocheck.add((x, 'in_state', newstate))
       
   425     # delete previous state first in case we're using a super session
       
   426     session.delete_relation(x, 'in_state', oldstate)
       
   427     session.add_relation(x, 'in_state', newstate)
       
   428 
   420 
   429 
   421 def before_add_trinfo(session, entity):
   430 def before_add_trinfo(session, entity):
   422     """check the transition is allowed, add missing information. Expect that:
   431     """check the transition is allowed, add missing information. Expect that:
   423     * wf_info_for inlined relation is set
   432     * wf_info_for inlined relation is set
   424     * by_transition or to_state (managers only) inlined relation is set
   433     * by_transition or to_state (managers only) inlined relation is set
   475     entity['to_state'] = deststateeid
   484     entity['to_state'] = deststateeid
   476     nocheck = session.transaction_data.setdefault('skip-security', set())
   485     nocheck = session.transaction_data.setdefault('skip-security', set())
   477     nocheck.add((entity.eid, 'from_state', fromstate.eid))
   486     nocheck.add((entity.eid, 'from_state', fromstate.eid))
   478     nocheck.add((entity.eid, 'to_state', deststateeid))
   487     nocheck.add((entity.eid, 'to_state', deststateeid))
   479 
   488 
       
   489 
   480 def after_add_trinfo(session, entity):
   490 def after_add_trinfo(session, entity):
   481     """change related entity state"""
   491     """change related entity state"""
   482     # need to delete previous state first, not done automatically since
   492     _change_state(session, entity['wf_info_for'],
   483     # we're using a super session
   493                   entity['from_state'], entity['to_state'])
   484     session.unsafe_execute('DELETE X in_state S WHERE X eid %(x)s, S eid %(s)s',
       
   485                            {'x': entity['wf_info_for'], 's': entity['from_state']},
       
   486                            ('x', 's'))
       
   487     session.unsafe_execute('SET X in_state S WHERE X eid %(x)s, S eid %(s)s',
       
   488                            {'x': entity['wf_info_for'], 's': entity['to_state']},
       
   489                            ('x', 's'))
       
   490 
   494 
   491 
   495 
   492 class SetInitialStateOp(PreCommitOperation):
   496 class SetInitialStateOp(PreCommitOperation):
   493     """make initial state be a default state"""
   497     """make initial state be a default state"""
   494 
   498 
   508 
   512 
   509 
   513 
   510 def set_initial_state_after_add(session, entity):
   514 def set_initial_state_after_add(session, entity):
   511     SetInitialStateOp(session, entity=entity)
   515     SetInitialStateOp(session, entity=entity)
   512 
   516 
       
   517 
       
   518 class WorkflowChangedOp(PreCommitOperation):
       
   519     """fix entity current state when changing its workflow"""
       
   520 
       
   521     def precommit_event(self):
       
   522         session = self.session
       
   523         pendingeids = session.transaction_data.get('pendingeids', ())
       
   524         if self.eid in pendingeids:
       
   525             return
       
   526         entity = session.entity_from_eid(self.eid)
       
   527         # notice that enforcment that new workflow apply to the entity's type is
       
   528         # done by schema rule, no need to check it here
       
   529         if entity.current_workflow.eid == self.wfeid:
       
   530             deststate = entity.current_workflow.initial
       
   531             if not deststate:
       
   532                 msg = session._('workflow has no initial state')
       
   533                 raise ValidationError(entity.eid, {'custom_workflow': msg})
       
   534             if entity.current_workflow.state_by_eid(entity.current_state.eid):
       
   535                 # nothing to do
       
   536                 return
       
   537             # if there are no history, simply go to new workflow's initial state
       
   538             if not entity.workflow_history:
       
   539                 if entity.current_state.eid != deststate.eid:
       
   540                     _change_state(session, entity.eid,
       
   541                                   entity.current_state.eid, deststate.eid)
       
   542                 return
       
   543             msg = session._('workflow changed to "%s"')
       
   544             msg %= entity.current_workflow.name
       
   545             entity.change_state(deststate.name, msg)
       
   546 
       
   547 
       
   548 def set_custom_workflow(session, eidfrom, rtype, eidto):
       
   549     WorkflowChangedOp(session, eid=eidfrom, wfeid=eidto)
       
   550 
       
   551 
       
   552 def del_custom_workflow(session, eidfrom, rtype, eidto):
       
   553     entity = session.entity_from_eid(eidfrom)
       
   554     typewf = entity.cwetype_workflow()
       
   555     if typewf is not None:
       
   556         WorkflowChangedOp(session, eid=eidfrom, wfeid=typewf.eid)
       
   557 
       
   558 
   513 def after_del_workflow(session, eid):
   559 def after_del_workflow(session, eid):
   514     # workflow cleanup
   560     # workflow cleanup
   515     session.execute('DELETE State X WHERE NOT X state_of Y')
   561     session.execute('DELETE State X WHERE NOT X state_of Y')
   516     session.execute('DELETE Transition X WHERE NOT X transition_of Y')
   562     session.execute('DELETE Transition X WHERE NOT X transition_of Y')
   517 
   563 
   524         #hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state')
   570         #hm.register_hook(relation_deleted, 'before_delete_relation', 'in_state')
   525         for eschema in hm.schema.entities():
   571         for eschema in hm.schema.entities():
   526             if 'in_state' in eschema.subject_relations():
   572             if 'in_state' in eschema.subject_relations():
   527                 hm.register_hook(set_initial_state_after_add, 'after_add_entity',
   573                 hm.register_hook(set_initial_state_after_add, 'after_add_entity',
   528                                  str(eschema))
   574                                  str(eschema))
       
   575         hm.register_hook(set_custom_workflow, 'after_add_relation', 'custom_workflow')
       
   576         hm.register_hook(del_custom_workflow, 'after_delete_relation', 'custom_workflow')
   529         hm.register_hook(after_del_workflow, 'after_delete_entity', 'Workflow')
   577         hm.register_hook(after_del_workflow, 'after_delete_entity', 'Workflow')
   530 
   578 
   531 
   579 
   532 # CWProperty hooks #############################################################
   580 # CWProperty hooks #############################################################
   533 
   581