For recording only; Today I found another use case and I monkey paid Products.DCWorkflow as proof of concept:
configure.zcml
<configure xmlns="http://namespaces.zope.org/zope" xmlns:monkey="http://namespaces.plone.org/monkey"> <monkey:patch description="Allow aborting workflow transitions" class="Products.DCWorkflow.DCWorkflow.DCWorkflowDefinition" original="doActionFor" replacement=".patches.doActionFor" /> <subscriber for="Products.DCWorkflow.interfaces.IBeforeTransitionEvent" handler=".subscribers.validate_workflow_transition" /> </configure>
subscribers.py
def validate_workflow_transition(event): if not check_something(): raise MyException
patches.py
def doActionFor(self, ob, action, comment='', **kw): ...
The proof of concept worked as expected, but I was not happy with the final user interface, so I decided to follow Martijn's advice and re-execute everything as a guard; he will need additional code to establish protection in all related transitions of the workflow (and delete them when deleted), as well as view and view the browser to display a message explaining why the transition is not available, but in the end it will be cleaner.
source share