[Erp5-report] r30010 - in /erp5/trunk/products: ERP5/ ERP5Type/ ERP5Type/dtml/ ERP5Type/pat...

nobody at svn.erp5.org nobody at svn.erp5.org
Mon Oct 26 17:34:03 CET 2009


Author: leonardo
Date: Mon Oct 26 17:34:00 2009
New Revision: 30010

URL: http://svn.erp5.org?rev=30010&view=rev
Log:
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)

Added:
    erp5/trunk/products/ERP5Type/Workflow.py
    erp5/trunk/products/ERP5Type/dtml/addWorkflow.dtml
Modified:
    erp5/trunk/products/ERP5/InteractionWorkflow.py
    erp5/trunk/products/ERP5Type/__init__.py
    erp5/trunk/products/ERP5Type/patches/DCWorkflow.py

Modified: erp5/trunk/products/ERP5/InteractionWorkflow.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/InteractionWorkflow.py?rev=30010&r1=30009&r2=30010&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/InteractionWorkflow.py [utf8] (original)
+++ erp5/trunk/products/ERP5/InteractionWorkflow.py [utf8] Mon Oct 26 17:34:00 2009
@@ -26,7 +26,7 @@
 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
 

Added: erp5/trunk/products/ERP5Type/Workflow.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Workflow.py?rev=30010&view=auto
==============================================================================
--- erp5/trunk/products/ERP5Type/Workflow.py (added)
+++ erp5/trunk/products/ERP5Type/Workflow.py [utf8] Mon Oct 26 17:34:00 2009
@@ -1,0 +1,205 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2002 Nexedi SA and Contributors. All Rights Reserved.
+#                    Jean-Paul Smets-Solanes <jp at 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')

Modified: erp5/trunk/products/ERP5Type/__init__.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/__init__.py?rev=30010&r1=30009&r2=30010&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/__init__.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/__init__.py [utf8] Mon Oct 26 17:34:00 2009
@@ -55,6 +55,9 @@
 # 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 @@
                          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()

Added: erp5/trunk/products/ERP5Type/dtml/addWorkflow.dtml
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/dtml/addWorkflow.dtml?rev=30010&view=auto
==============================================================================
--- erp5/trunk/products/ERP5Type/dtml/addWorkflow.dtml (added)
+++ erp5/trunk/products/ERP5Type/dtml/addWorkflow.dtml [utf8] Mon Oct 26 17:34:00 2009
@@ -1,0 +1,31 @@
+<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>

Modified: erp5/trunk/products/ERP5Type/patches/DCWorkflow.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/patches/DCWorkflow.py?rev=30010&r1=30009&r2=30010&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/patches/DCWorkflow.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/patches/DCWorkflow.py [utf8] Mon Oct 26 17:34:00 2009
@@ -608,94 +608,3 @@
 
 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')




More information about the Erp5-report mailing list