Jonathan Gutow
Jonathan Gutow

Reputation: 305

How do I add trusted code to a plone 4.x product that can be used by or as a workflow transition script?

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

Answers (1)

Martijn Pieters
Martijn Pieters

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 object
  • workflow: the current applicable workflow object
  • old_state: a Products.DCWorkflow.States.StateDefinition object
  • new_state: another Products.DCWorkflow.States.StateDefinition object
  • transition: a Products.DCWorkflow.Transititions.TransitionDefinition object
  • status: 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

Related Questions