From bad65600922cf8fae198a740ef28e7f739f07530 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Sat, 25 Nov 2006 10:49:41 +0000
Subject: [PATCH] Patch DCWorkflow again to use ERP5 Cache Tool to control
 worklists caching. Each workflow can use a different cache factory (default
 cache is used if nothing defined).

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@11483 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../ERP5Type/dtml/workflow_properties.dtml    | 16 ++++++++
 product/ERP5Type/patches/DCWorkflow.py        | 34 +++++++++++------
 product/ERP5Type/tests/testCacheTool.py       | 38 +++++++++++++++++++
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/product/ERP5Type/dtml/workflow_properties.dtml b/product/ERP5Type/dtml/workflow_properties.dtml
index acb96e6318..d9e6abaa6e 100644
--- a/product/ERP5Type/dtml/workflow_properties.dtml
+++ b/product/ERP5Type/dtml/workflow_properties.dtml
@@ -19,6 +19,22 @@
 <td><textarea name="description" rows="5" cols="80">&dtml-description;</textarea></td>
 </tr>
 
+<dtml-if "context.portal_caches">
+<tr>
+<th align="left">Worklists Cache</th>
+<td>
+  <select name="cache_factory_id" >
+  <option value=""/>
+  <dtml-in "context.portal_caches.objectItems()">
+    <option value="&dtml-sequence-key;" 
+       <dtml-if "_['sequence-key']==getattr(context, 'cache_factory_id', '')">SELECTED</dtml-if>
+    >&dtml-title_or_id;</option>
+  </dtml-in>
+  </select>
+</td>
+</tr>
+</dtml-if>
+
 <tr>
 <th align="left">'Manager' role bypasses guards</th>
 <td>
diff --git a/product/ERP5Type/patches/DCWorkflow.py b/product/ERP5Type/patches/DCWorkflow.py
index ff4a483525..03e49eba67 100644
--- a/product/ERP5Type/patches/DCWorkflow.py
+++ b/product/ERP5Type/patches/DCWorkflow.py
@@ -26,6 +26,7 @@ from Products.CMFCore.utils import  _getAuthenticatedUser
 from DocumentTemplate.DT_Util import TemplateDict
 from DateTime import DateTime
 from Products.ERP5Type.Cache import CachingMethod
+from Products.ERP5Type.Cache import DEFAULT_CACHE_FACTORY
 from Products.ERP5Type.Utils import convertToMixedCase
 from string import join
 from zLOG import LOG
@@ -36,14 +37,16 @@ from zLOG import LOG
 from Products.DCWorkflow.WorkflowUIMixin import WorkflowUIMixin as WorkflowUIMixin_class
 from Products.DCWorkflow.Guard import Guard
 
-def WorkflowUIMixin_setProperties( self, title
-                                 , description='' # the only addition to WorkflowUIMixin.setProperties
-                                 , manager_bypass=0, props=None, REQUEST=None):
+# patched to add a description on worklist for ERP5 Web, and to add the cache
+# control for worklists
+def WorkflowUIMixin_setProperties( self, title, description='',
+            cache_factory_id='', manager_bypass=0, props=None, REQUEST=None):
   """Sets basic properties.
   """
   self.title = str(title)
   self.description = str(description)
   self.manager_bypass = manager_bypass and 1 or 0
+  self.cache_factory_id = cache_factory_id
   g = Guard()
   if g.changeFromProperties(props or REQUEST):
       self.creation_guard = g
@@ -57,6 +60,7 @@ WorkflowUIMixin_class.setProperties = WorkflowUIMixin_setProperties
 WorkflowUIMixin_class.manage_properties = DTMLFile('workflow_properties', _dtmldir)
 
 
+DCWorkflowDefinition_listGlobalActions_original = DCWorkflowDefinition.listGlobalActions
 
 def DCWorkflowDefinition_listGlobalActions(self, info):
     '''
@@ -65,11 +69,12 @@ def DCWorkflowDefinition_listGlobalActions(self, info):
     Called on every request.
     Returns the actions to be displayed to the user.
     '''
+    if not self.worklists:
+      return None  # Optimization
+
+    portal = self._getPortalRoot()
     def _listGlobalActions(user=None, id=None, portal_path=None):
-      if not self.worklists:
-          return None  # Optimization
       sm = getSecurityManager()
-      portal = self._getPortalRoot()
       res = []
       fmt_data = None
       # We want to display some actions depending on the current date
@@ -96,7 +101,6 @@ def DCWorkflowDefinition_listGlobalActions(self, info):
                   if not (guard is None or guard.check(sm, self, portal)):
                       dict['local_roles'] = guard.roles
                   # Patch to use ZSQLCatalog and get high speed
-                  # LOG("PatchedDCWorkflowDefinition", 0, dict)
                   searchres_len = int(apply(catalog.countResults, (), dict)[0][0])
                   if searchres_len == 0:
                       continue
@@ -121,11 +125,17 @@ def DCWorkflowDefinition_listGlobalActions(self, info):
       res.sort()
       return map((lambda (id, val): val), res)
 
-    # Return Cache
-    _listGlobalActions = CachingMethod(_listGlobalActions, id='listGlobalActions', cache_duration = 300)
-    user = str(_getAuthenticatedUser(self))
-    return _listGlobalActions(user=user, id=self.id, portal_path=self._getPortalRoot().getPhysicalPath())
-
+    cache_tool = getToolByName(self, 'portal_caches', None)
+    if cache_tool is not None:
+      # If we have a cache factory controlling this workflow's worklist cache
+      cache_factory = getattr(self, 'cache_factory_id', DEFAULT_CACHE_FACTORY)
+      _listGlobalActions = CachingMethod(_listGlobalActions,
+                                         id='%s_listGlobalActions' % self.id,
+                                         cache_factory=cache_factory)
+      user = str(_getAuthenticatedUser(self))
+      return _listGlobalActions(user=user, portal_path=portal.getPhysicalPath())
+    else:
+      return DCWorkflowDefinition_listGlobalActions_original(self, info)
 
 DCWorkflowDefinition.listGlobalActions = DCWorkflowDefinition_listGlobalActions
 
diff --git a/product/ERP5Type/tests/testCacheTool.py b/product/ERP5Type/tests/testCacheTool.py
index 95d743a5d7..9ea774ad8b 100644
--- a/product/ERP5Type/tests/testCacheTool.py
+++ b/product/ERP5Type/tests/testCacheTool.py
@@ -282,6 +282,44 @@ return result
       ## Cache  cleared shouldn't be previously cached
       self.assert_(1.0 < calculation_time)
 
+  def test_DCWorkflowIntegration(self, quiet=0, run=run_all_test):
+    """ Test Wokflow caching DCWorkflow global actions"""
+    portal = self.getPortal()
+    # set up caching environnement
+    ctool = portal.portal_caches
+    first_factory = ctool.newContent(portal_type='Cache Factory',
+                                     id='first_factory')
+    first_factory_cache = TestingCache({})
+    second_factory = ctool.newContent(portal_type='Cache Factory',
+                                     id='second_factory')
+    second_factory_cache = TestingCache({})
+    # emulate CachingMethod.factories initialization
+    CachingMethod.factories['first_factory'] = first_factory_cache
+    CachingMethod.factories['second_factory'] = second_factory_cache
+
+    # setup two workflows with different cache factories
+    wftool = portal.portal_workflow
+    wftool.manage_addWorkflow('erp5_workflow (ERP5-style empty workflow)',
+                              'first_workflow')
+    first_workflow = wftool._getOb('first_workflow')
+    first_workflow.cache_factory_id = 'first_factory'
+    first_workflow.worklists.addWorklist('dummy_worklist')
+
+    wftool.manage_addWorkflow('erp5_workflow (ERP5-style empty workflow)',
+                              'second_workflow')
+    second_workflow = wftool._getOb('second_workflow')
+    second_workflow.cache_factory_id = 'second_factory'
+    second_workflow.worklists.addWorklist('dummy_worklist')
+
+    # listing actions will use the corresponding cache
+    info = wftool._getOAI(ctool)
+    first_workflow.listGlobalActions(info)
+    self.assertEquals(1, first_factory_cache.getCacheMisses())
+    self.assertEquals(0, second_factory_cache.getCacheMisses())
+    second_workflow.listGlobalActions(info)
+    self.assertEquals(1, first_factory_cache.getCacheMisses())
+    self.assertEquals(1, second_factory_cache.getCacheMisses())
+
 if __name__ == '__main__':
     framework()
 else:
-- 
2.30.9