From e82629699b486623f6fa4a8deea2423a2101093a Mon Sep 17 00:00:00 2001
From: Jean-Paul Smets <jp@nexedi.com>
Date: Thu, 24 Dec 2009 17:09:36 +0000
Subject: [PATCH] Initial implementatoin of mass workflow state change was
 playing arround the API of SelectionTool and Selection, getting parameters
 and reimplementing part of Selection.__call__ API in order to be able to
 override certain parameters. As a result, some parameters were not taken into
 account in some cases and the result was not the same as the one from the
 selection. In this change, we extend the API of Selection so that, just like
 for methods, it is possible to override in a non persistent way the
 parameters which are passed to the selection method. This is similar to the
 existing possibility of overriding the calling context or the selection
 method.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@31466 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../Folder_getWorkflowActionDocumentList.py   | 29 ++++++++-----------
 product/ERP5Form/Selection.py                 | 23 +++++++++++++--
 product/ERP5Form/Tool/SelectionTool.py        | 26 +++++++++++++++--
 3 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/product/ERP5Form/Extensions/Folder_getWorkflowActionDocumentList.py b/product/ERP5Form/Extensions/Folder_getWorkflowActionDocumentList.py
index e8ae27ea38..49b7757de6 100644
--- a/product/ERP5Form/Extensions/Folder_getWorkflowActionDocumentList.py
+++ b/product/ERP5Form/Extensions/Folder_getWorkflowActionDocumentList.py
@@ -53,11 +53,8 @@ def getDocumentGroupByWorkflowStateList(self, form_id='', **kw):
   
   selection_name = request['selection_name']
 
-  list_method_name = 'searchFolder'
   form = getattr(portal, form_id)
   listbox = getattr(form, 'listbox', None)
-  if listbox is not None:
-    list_method_name = listbox.get_value('list_method').method_name
 
   # guess all column name from catalog schema
   possible_state_list = [column_name for column_name in
@@ -72,17 +69,17 @@ def getDocumentGroupByWorkflowStateList(self, form_id='', **kw):
   counter = 0
   if not selection_uid_list:
     for workflow_state in possible_state_list:
-      selection_params = \
-              selection_tool.getSelectionParamsFor(selection_name).copy()
-      selection_params['where_expression'] = \
-                        'catalog.%s is not NULL' % workflow_state
-      selection_params['group_by'] = ('catalog.portal_type',
+      params = \
+          selection_tool.getSelectionParamsFor(selection_name).copy() 
+      params['where_expression'] = \
+                       'catalog.%s is not NULL' % workflow_state
+      params['group_by'] = ('catalog.portal_type',
                                       'catalog.%s' % workflow_state)
-      selection_params['select_expression'] = (
+      params['select_expression'] = (
           'catalog.path, count(catalog.uid) as count, catalog.portal_type, catalog.%s'
             % workflow_state)
       
-      for brain in getattr(self, list_method_name)(**selection_params):
+      for brain in selection_tool.callSelectionFor(selection_name, params=params):
         doc = brain.getObject()
         for workflow in wf_tool.getWorkflowsFor(doc):
           state_var = workflow.variables.getStateVar()
@@ -161,13 +158,10 @@ def getWorkflowActionDocumentList(self, **kw):
   document_list = []
   portal = self.getPortalObject()
   getObject = portal.portal_catalog.getObject
-  searchResults = portal.portal_catalog.searchResults
   wtool = portal.portal_workflow
-  stool = portal.portal_selections
-  original_selection_params = stool.getSelectionParamsFor(selection_name)
-  original_selection_params.setdefault('sort_on', kw.get('sort_on'))
+  selection_tool = portal.portal_selections
 
-  selection_uid_list = stool.getSelectionCheckedUidsFor(selection_name)
+  selection_uid_list = selection_tool.getSelectionCheckedUidsFor(selection_name)
 
   if selection_uid_list:
     original_selection_params['uid'] = selection_uid_list
@@ -175,14 +169,15 @@ def getWorkflowActionDocumentList(self, **kw):
   translate = self.Base_translateString
   for listbox_selection in listbox:
     if listbox_selection.get('workflow_action'):
-      selection_params = original_selection_params.copy()
+      selection_params = selection_tool.getSelectionParamsFor(selection_name).copy() 
+      selection_params.setdefault('sort_on', kw.get('sort_on'))
       selection_params[listbox_selection['state_var']] = \
                                 listbox_selection['workflow_state']
       selection_params['portal_type'] = listbox_selection['portal_type']
 
       workflow_id, action = listbox_selection['workflow_action'].split('/')
       workflow = wtool.getWorkflowById(workflow_id)
-      for doc in searchResults(**selection_params):
+      for doc in selection_tool.callSelectionFor(selection_name, params=selection_params):
         doc = doc.getObject()
         action_list = [ai for ai in
                         workflow.listObjectActions(wtool._getOAI(doc))
diff --git a/product/ERP5Form/Selection.py b/product/ERP5Form/Selection.py
index 029edaf1db..29a2999458 100644
--- a/product/ERP5Form/Selection.py
+++ b/product/ERP5Form/Selection.py
@@ -185,11 +185,30 @@ class Selection(Acquisition.Implicit, Traversable, Persistent):
          restarted."""
       return newState
 
-    def __call__(self, method = None, context=None, REQUEST=None):
+    def __call__(self, method=None, context=None, REQUEST=None, params=None):
+        """
+        Calls the selection and return the list of selected documents
+        or objects. Seledction method, context and parameters may be 
+        overriden in a non persistent way.
+
+        method -- optional method (callable) or method path (string)
+                  to use instead of the persistent selection method
+
+        context -- optional context to call the selection method on
+
+        REQUEST -- optional REQUEST parameters (not used, only to 
+                   provide API compatibility)
+
+        params -- optional parameters which can be used to override
+                  default params
+        """
         #LOG("Selection", 0, str((self.__dict__)))
         #LOG("Selection", 0, str(method))
         #LOG('Selection', 0, "self.invert_mode = %s" % repr(self.invert_mode))
-        kw = self.params.copy()
+        if not params:
+          kw = self.params.copy()
+        else:
+          kw = params.copy()
         # Always remove '-C'-named parameter.
         kw.pop('-C', None)
         if self.invert_mode is not 0:
diff --git a/product/ERP5Form/Tool/SelectionTool.py b/product/ERP5Form/Tool/SelectionTool.py
index ecffd7fcdc..b9784a2735 100644
--- a/product/ERP5Form/Tool/SelectionTool.py
+++ b/product/ERP5Form/Tool/SelectionTool.py
@@ -220,12 +220,34 @@ class SelectionTool( BaseTool, UniqueObject, SimpleItem ):
       return self.getSelectionNameList(context, REQUEST)
 
     security.declareProtected(ERP5Permissions.View, 'callSelectionFor')
-    def callSelectionFor(self, selection_name, context=None, REQUEST=None):
+    def callSelectionFor(self, selection_name, method=None, context=None, 
+                                               REQUEST=None, params=None):
+      """
+      Calls the selection and return the list of selected documents
+      or objects. Seledction method, context and parameters may be 
+      overriden in a non persistent way.
+
+      selection_name -- the name of the selectoin (string)
+
+      method -- optional method (callable) or method path (string)
+                to use instead of the persistent selection method
+
+      context -- optional context to call the selection method on
+
+      REQUEST -- optional REQUEST parameters (not used, only to 
+                 provide API compatibility)
+
+      params -- optional parameters which can be used to override
+                default params
+
+      TODO: is it acceptable to keep method in the API at this level
+            for security reasons (XXX-JPS)
+      """
       if context is None: context = self
       selection = self.getSelectionFor(selection_name, REQUEST=REQUEST)
       if selection is None:
         return None
-      return selection(context=context)
+      return selection(method=method, context=context, REQUEST=REQUEST, params=params)
 
     security.declareProtected(ERP5Permissions.View, 'getSelectionFor')
     def getSelectionFor(self, selection_name, REQUEST=None):
-- 
2.30.9