Create a new ERP5Type/Workflow.py file to house all changes needed as we...

Create a new ERP5Type/Workflow.py file to house all changes needed as we progressively remove DCWorkflow dependencies. For now it contains the non-patches part of patches/DCWorkflow.py and a conditional replacement for addWorkflowFactory() function that disappeared on CMF 2. Adjust other import locations to point to this function. Adjust ERP5Type product initialization to register Zope2-style factories for workflows registered with the substitute addWorkflowFactory when on CMF2 (approved by jm and jerome)

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30010 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 0b07c7bb
......@@ -26,7 +26,7 @@ from Products.CMFCore.utils import getToolByName
from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.DCWorkflow.Expression import StateChangeInfo, createExprContext
from Products.ERP5Type.patches.DCWorkflow import addWorkflowFactory
from Products.ERP5Type.Workflow import addWorkflowFactory
from Products.CMFActivity.ActiveObject import ActiveObject
from Products.ERP5Type import Permissions
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import zLOG
from Products.ERP5Type import Permissions
from App.special_dtml import HTMLFile
from Acquisition import aq_inner
from AccessControl.requestmethod import postonly
from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
# ERP5 workflow factory definitions
_workflow_factories = {}
try:
from Products.CMFCore.WorkflowTool import addWorkflowFactory
# We're on CMF 1.5
except ImportError:
# We're on CMF 2
zLOG.LOG('Products.ERP5Type.Workflow.addWorkflowFactory',
zLOG.INFO,
summary='Registering Workflow Factories Directly',
detail='Products.CMFCore.WorkflowTool.addWorkflowFactory has '
'been removed from CMFCore. Workflows will be registered as '
'Zope 2 style factories instead.')
def addWorkflowFactory(factory, id, title):
"""addWorkflowFactory replacement
addWorkflowFactory has been removed from CMFCore 2.x.
DCWorkflow, which now handles this job, consults the GenericSetup tool,
at runtime, to determine all valid workflows.
Instead of providing xml files in GenericSetup profiles for our,
workflows we prepare our own Zope2 style factories for registration
in the Workflow Tool.
"""
assert not _workflow_factories.get(id), (
'Workflow with id %r already exists.' % id)
factory_info = dict(factory=factory,
id=id,
title=title)
_workflow_factories[id] = factory_info
# Workflow Creation DTML
manage_addWorkflowFormDtml = HTMLFile('dtml/addWorkflow', globals())
def _generateWorkflowConstructors(factory_info):
""" Generate a "manage_addWorkflow_?" and "manage_addWorkflowForm_?" methods
specific for each workflow factory. """
FACTORY_FORM_PREFIX = 'addWorkflowForm_'
FACTORY_ACTION_PREFIX = 'addWorkflow_'
workflow_factory_id = factory_info['id']
workflow_factory_title = factory_info['title']
# the method names (last url segments)
constructor_form_name=FACTORY_FORM_PREFIX + workflow_factory_id
constructor_action_name=FACTORY_ACTION_PREFIX + workflow_factory_id
# The form
def manage_addWorkflowForm(dispatcher, REQUEST, RESPONSE):
"""Form to add a type-specific workflow to portal_workflow"""
kw = dict(workflow_factory_title=workflow_factory_title,
form_action=constructor_action_name)
return manage_addWorkflowFormDtml(None, dispatcher, REQUEST, **kw)
# The action of the form
@postonly
def manage_addWorkflow(dispatcher, workflow_id, REQUEST=None):
"""Add a type specific workflow with object-id as 'workflow_id'
"""
# we could have just used the factory from factory_info here, but we use
# addWorkflowByType to exercise it.
addWorkflowByType(dispatcher, workflow_factory_id, workflow_id)
if REQUEST is not None:
return REQUEST.response.redirect(dispatcher.DestinationURL() +
"/manage_main")
return workflow
# The constructors
constructors = [(constructor_form_name, manage_addWorkflowForm),
(constructor_action_name, manage_addWorkflow)]
return constructors
def addWorkflowByType(container, workflow_factory_id, workflow_id):
""" Add a workflow with name 'workflow_id' from factory identified by
'workflow_factory_id'
"""
# This functionality could be inside the generated manage_addWorkflow above,
# but is placed here to be easily used directly from Python code.
workflow_factory = _workflow_factories[workflow_factory_id]['factory']
workflow = workflow_factory(workflow_id)
container._setObject(workflow_id, workflow)
return aq_inner(container.restrictedTraverse(workflow_id))
def registerWorkflowFactory(context, factory_info):
""" Register a workflow factory as a Zope2 style object factory that is only
addable to portal_workflow"""
constructors = _generateWorkflowConstructors(factory_info)
permission = Permissions.ManagePortal
context.registerClass(DCWorkflowDefinition, # this class is only used here for its interfaces
meta_type=factory_info['title'],
constructors=constructors,
permission=permission,
visibility=None)
def registerAllWorkflowFactories(context):
"""register workflow factories during product initialization
"""
# the loop below will be empty on CMF 1.5, as the original addworkflowFactory
# from CMF will not populate this WORKFLOW_FACTORIES dictionary.
for factory_info in _workflow_factories.itervalues():
registerWorkflowFactory(context, factory_info)
# Add a workflow factory for ERP5 style workflow, because some variables
# are needed for History tab.
def setupERP5Workflow(wf):
"""Sets up an DC Workflow with defaults variables needed by ERP5.
"""
wf.setProperties(title='ERP5 default workflow')
for s in ('draft',):
wf.states.addState(s)
for v in ('action', 'actor', 'comment', 'history', 'time',
'error_message', 'portal_type'):
wf.variables.addVariable(v)
for perm in (Permissions.AccessContentsInformation,
Permissions.View,
Permissions.AddPortalContent,
Permissions.ModifyPortalContent,
Permissions.DeleteObjects):
wf.addManagedPermission(perm)
wf.states.setInitialState('draft')
# set by default the state variable to simulation_state.
# anyway, a default workflow needs to be configured.
wf.variables.setStateVar('simulation_state')
vdef = wf.variables['action']
vdef.setProperties(description='The last transition',
default_expr='transition/getId|nothing',
for_status=1, update_always=1)
vdef = wf.variables['actor']
vdef.setProperties(description='The name of the user who performed '
'the last transition',
default_expr='user/getUserName',
for_status=1, update_always=1)
vdef = wf.variables['comment']
vdef.setProperties(description='Comments about the last transition',
default_expr="python:state_change.kwargs.get('comment', '')",
for_status=1, update_always=1)
vdef = wf.variables['history']
vdef.setProperties(description='Provides access to workflow history',
default_expr="state_change/getHistory")
vdef = wf.variables['time']
vdef.setProperties(description='Time of the last transition',
default_expr="state_change/getDateTime",
for_status=1, update_always=1)
vdef = wf.variables['error_message']
vdef.setProperties(description='Error message if validation failed',
for_status=1, update_always=1)
vdef = wf.variables['portal_type']
vdef.setProperties(description='portal type (use as filter for worklists)',
for_catalog=1)
def createERP5Workflow(id):
"""Creates an ERP5 Workflow """
ob = DCWorkflowDefinition(id)
setupERP5Workflow(ob)
return ob
addWorkflowFactory(createERP5Workflow,
id='erp5_workflow',
title='ERP5-style empty workflow')
......@@ -55,6 +55,9 @@ import Products.Localizer # So that we make sure Globals.get_request is availabl
# production environment
class_tool_security_path = '%s%s%s' % (product_path, os.sep, 'ALLOW_CLASS_TOOL')
# allow our workflow definitions to be registered
import Products.ERP5Type.Workflow
def allowClassTool():
return os.access(class_tool_security_path, os.F_OK)
......@@ -84,6 +87,8 @@ def initialize( context ):
portal_tools = portal_tools,
content_constructors = content_constructors,
content_classes = content_classes)
# Register our Workflow factories directly (if on CMF 2)
Products.ERP5Type.Workflow.registerAllWorkflowFactories(context)
# We should register local constraints at some point
from Products.ERP5Type.Utils import initializeLocalConstraintRegistry
initializeLocalConstraintRegistry()
......
<dtml-let form_title="'Add ' + workflow_factory_title" BASEPATH1="BASE1">
<dtml-var manage_page_header>
<dtml-var manage_form_title>
</dtml-let>
<form action="&dtml-form_action;" method="POST">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="workflow_id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
......@@ -608,94 +608,3 @@ def getAvailableScriptIds(self):
TransitionDefinition.getAvailableScriptIds = getAvailableScriptIds
# Add a workflow factory for ERP5 style workflow, because some variables
# are needed for History tab.
try:
from Products.CMFCore.WorkflowTool import addWorkflowFactory
except ImportError:
def addWorkflowFactory(factory, id, title):
"""addWorkflowFactory replacement
addWorkflowFactory has been removed from CMF 2.x.
DCWorkflow, which actually handled the workflows added by this function
now consults the GenericSetup tool, at runtime to determine all valid
workflows.
Instead of providing GenericSetup profiles for our workflows, we
install our own Zope2 style factories for the Workflow Tool
"""
import zLOG
zLOG.LOG('Products.ERP5Type.patches.DCWorkflow.addWorkflowFactory',
zLOG.ERROR,
summary='Workflow Factory not registered',
detail='Products.CMFCore.WorkflowTool.addWorkflowFactory has '
'been removed from CMFCore, and a replacement has not been '
'written yet. ERP5 Workflow factory for '
'%s (%s) not installed.' % (id, title))
from Products.ERP5Type import Permissions
def setupERP5Workflow(wf):
"""Sets up an DC Workflow with defaults variables needed by ERP5.
"""
wf.setProperties(title='ERP5 default workflow')
for s in ('draft',):
wf.states.addState(s)
for v in ('action', 'actor', 'comment', 'history', 'time',
'error_message', 'portal_type'):
wf.variables.addVariable(v)
for perm in (Permissions.AccessContentsInformation,
Permissions.View,
Permissions.AddPortalContent,
Permissions.ModifyPortalContent,
Permissions.DeleteObjects):
wf.addManagedPermission(perm)
wf.states.setInitialState('draft')
# set by default the state variable to simulation_state.
# anyway, a default workflow needs to be configured.
wf.variables.setStateVar('simulation_state')
vdef = wf.variables['action']
vdef.setProperties(description='The last transition',
default_expr='transition/getId|nothing',
for_status=1, update_always=1)
vdef = wf.variables['actor']
vdef.setProperties(description='The name of the user who performed '
'the last transition',
default_expr='user/getUserName',
for_status=1, update_always=1)
vdef = wf.variables['comment']
vdef.setProperties(description='Comments about the last transition',
default_expr="python:state_change.kwargs.get('comment', '')",
for_status=1, update_always=1)
vdef = wf.variables['history']
vdef.setProperties(description='Provides access to workflow history',
default_expr="state_change/getHistory")
vdef = wf.variables['time']
vdef.setProperties(description='Time of the last transition',
default_expr="state_change/getDateTime",
for_status=1, update_always=1)
vdef = wf.variables['error_message']
vdef.setProperties(description='Error message if validation failed',
for_status=1, update_always=1)
vdef = wf.variables['portal_type']
vdef.setProperties(description='portal type (use as filter for worklists)',
for_catalog=1)
def createERP5Workflow(id):
"""Creates an ERP5 Workflow """
ob = DCWorkflowDefinition(id)
setupERP5Workflow(ob)
return ob
addWorkflowFactory(createERP5Workflow,
id='erp5_workflow',
title='ERP5-style empty workflow')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment