Ticket #9565 (closed PLIP: wontfix)
Use adaption for workflow history and status
Reported by: | dukebody | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | Future |
Component: | General | Version: | |
Keywords: | Cc: |
Description
http://plone.org/products/plone/roadmap/221
The other major area that the workflow tool makes difficult to customize is the storage of workflow history and status. This proposal attempts to address the issue by using adaption to determine how workflow history and status should be stored
Proposed by
Laurence Rowe
Proposal type
Architecture
Repository branch
adapterize-wfstatus-wfhistory
State
being-discussed
Motivation
Currently it is very difficult to use alternate mechanisms for storing workflow history. For example collective.tin needs a content mixin class defining a workflow_history property in order to store workflow history in a database.
This proposal is inspired by Kapil's work in cmfblackbird and my experience building collective.tin.
Proposal
Providing workflow history storage via adaptation is a pretty trivial task which can be made fully backward compatible. We simply need to replace the content of the WorkflowTool.getHistoryOf , setStatusOf methods with a lookup via adaptation:
def getHistoryOf(self, wf_id, ob):
""" Get the history of an object for a given workflow. """ return queryMultiAdapter((ob, wf_id), IWorkflowHistory, default=())
def setStatusOf(self, wf_id, ob, status):
""" Append a record to the workflow history of a given workflow. """ wfs = getMultiAdapter((ob, wf_id), IWorkflowStatus) wfs.set(status)
def getStatusOf(self, wf_id, ob):
""" Get the last element of a workflow history for a given workflow. """ wfs = queryMultiAdapter((ob, wf_id), IWorkflowStatus, default=None) if wfs:
return wfs.get()
return None
Multi-adapters on the content object and workflow id are used. This allows for content type developers and integrators to customise the storage of workflow status and optionally history for either all workflows or individual workflows (by registering a multiadapter for (IContentish, 'workflow_id'). The default adapters are simply:
class DefaultWorkflowStatus(object):
implements(IWorkflowStatus) adapts(IContentish, basestring)
def init(self, context, wf_id):
self.context = aq_base(context) self.wf_id = wf_id
def get(self):
history = getattr(self.context, 'workflow_history', {}) return history.get(self.wf_id, None)
def set(self, status):
history = getattr(self.context, 'workflow_history', None) if history is None:
history = self.context.workflow_history = PersistentMapping()
wfh = list(history.get(self.wf_id, ())) wfh.append(status) history[self.wf_id] = tuple(wfh)
@implementer(IWorkflowHistory) @adapter(IContentish, basestring) def default_workflow_history(context, wf_id):
history = getattr(aq_base(context), 'workflow_history', {}) return history.get(self.wf_id, ())
Interfaces are:
class IWorkflowStatus(Interface):
def get():
"""Return the workflow status"""
def set(status):
"""Update the workflow status to status"""
class IWorkflowHistory(Interface):
"""A sequence of workflow status dictionaries"""
Ideally this would be done in CMFCore. However, it's certainly feasible to do it inside of the CMFPlone workflow tool if no major release of CMF is imminent. The changes could easily be merged back into the core as needed. Deliverables
- The interfaces for IWorkflowHistory and IWorkflowStatus would need to be created.
- The getWorkflowHistory, setStatusOf and getStatusOf methods would need to be rewritten/overridden, and a test would need to be written to demonstrate the adaptation based mechanism.
- The default adapters would need to be created
- Some documentation on how to provide a custom workflow history and status storage should be provided.
Risks
There should be no risk as the WorkflowTool interface and default history storage remain consistent. The only risk is that our workflow tool will deviate further from the CMF version, hopefully we can get this code applied in CMFCore sooner rather than later.
Progress log
- Partially implemented in the branch to CMFCore. Needs tests and merging.
PLEASE READ THIS AND RE-OPEN VALID PLIPS!
As we launch the new PLIP process we'd like to see which PLIPs:
If this PLIP should still be considered for future releases of Plone please do re-open this ticket and assign an appropriate milestone. If it should be considered for the next release of Plone, use the 4.2 milestone. Also be sure to update the PLIP description, requester, owner, etc. and include a comment detailing recent progress and new plans. We will use all these details in the new continuous PLIP process.