Reputation: 305
I am trying to construct a workflow that can be assigned to arbitrary containers and will have the following behavior. When the container makes the transition from state A -> A', the contents of the container should be checked for their state and moved to a new state that depends on their present state. In other words:
and so on...
obj1 and obj2 are following the same workflow that branches to a number of final states (approved, denied, alternate, etc...)
I know how to do this, if I can trigger my python code as trusted code. Unfortunately, I have not been able to figure out how or where to put the code in my product so this will work. I have found references to using "external methods", however that seems to be going away. Also I want the code to reside in my project.
I think this is probably simple and I am overlooking something. Help with how to put this in my project or another route to achieving the same goal would be welcome.
Upvotes: 1
Views: 121
Reputation: 1123410
The scripts support for DCWorkflow only supports through-the-web-addable objects, which limits you to External Methods there.
A better bet is to use workflow events instead. For each workflow transition, two events are fired:
Products.DCWorkflow.interfaces.IAfterTransitionEvent
Products.DCWorkflow.interfaces.IBeforeTransitionEvent
If you subscribe to either of those events, you can then filter on the correct workflow and transistion to react to transitions from trusted code.
Each event fired has the following attributes:
object
: the workflowed objectworkflow
: the current applicable workflow objectold_state
: a Products.DCWorkflow.States.StateDefinition
objectnew_state
: another Products.DCWorkflow.States.StateDefinition
objecttransition
: a Products.DCWorkflow.Transititions.TransitionDefinition
objectstatus
: a dictionary with the current workflow variables kwargs
: a dictionary of extra arguments passed in to the change-transition call.Register a subscriber using ZCML:
<subscriber
provides="zope.component.testfiles.adapter.IS"
factory=".youreventsmodule.aftertransition_handler"
for="Products.DCWorkflow.interfaces.IAfterTransitionEvent"
/>
or, because the transition events are object events, listen only to the transition event if it applies to your objects:
<subscriber
provides="zope.component.testfiles.adapter.IS"
factory=".youreventsmodule.container_aftertransition_handler"
for=".interfaces.IMyContainerType
Products.DCWorkflow.interfaces.IAfterTransitionEvent"
/>
which registers your handler only for transition events on objects with the IMyContainerType
interface only.
The handler would be:
def aftertransition_handler(event):
# handle all transition events, ever
or, when limiting it to one object interface:
def aftertransition_handler(obj, event):
# handle all transition events for our container interface
Upvotes: 5