Back to index

plone3  3.1.7
DefaultWorkflowPolicy.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 ## CMFPlacefulWorkflow
00003 ## Copyright (C)2005 Ingeniweb
00004 
00005 ## This program is free software; you can redistribute it and/or modify
00006 ## it under the terms of the GNU General Public License as published by
00007 ## the Free Software Foundation; either version 2 of the License, or
00008 ## (at your option) any later version.
00009 
00010 ## This program is distributed in the hope that it will be useful,
00011 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ## GNU General Public License for more details.
00014 
00015 ## You should have received a copy of the GNU General Public License
00016 ## along with this program; see the file COPYING. If not, write to the
00017 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 """
00019 A simple workflow policy.
00020 """
00021 __version__ = "$Revision: 62540 $"
00022 # $Source: /cvsroot/ingeniweb/CMFPlacefulWorkflow/DefaultWorkflowPolicy.py,v $
00023 # $Id: DefaultWorkflowPolicy.py 62540 2008-04-12 07:50:01Z encolpe $
00024 __docformat__ = 'restructuredtext'
00025 
00026 import logging
00027 from os.path import join as path_join
00028 
00029 from AccessControl import ClassSecurityInfo
00030 from AccessControl.requestmethod import postonly
00031 from Globals import InitializeClass, PersistentMapping
00032 from Acquisition import aq_base
00033 
00034 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
00035 
00036 from Products.CMFCore.utils import SimpleItemWithProperties
00037 from Products.CMFPlacefulWorkflow.PlacefulWorkflowTool import addWorkflowPolicyFactory
00038 
00039 from Products.CMFCore.permissions import ManagePortal
00040 
00041 from Products.CMFPlacefulWorkflow.interfaces.portal_placeful_workflow import IWorkflowPolicyDefinition
00042 from Products.CMFPlacefulWorkflow.global_symbols import Log, LOG_DEBUG
00043 
00044 from Products.CMFCore.utils import getToolByName
00045 
00046 DEFAULT_CHAIN = '(Default)'
00047 _MARKER = '_MARKER'
00048 
00049 class DefaultWorkflowPolicyDefinition (SimpleItemWithProperties):
00050 
00051     __implements__ = IWorkflowPolicyDefinition
00052 
00053     meta_type = 'WorkflowPolicy'
00054     id = 'default_workflow_policy'
00055     _isAWorkflowPolicy = 1
00056 
00057     _chains_by_type = None  # PersistentMapping
00058     _default_chain = None # Fallback to wf tool
00059 
00060     security = ClassSecurityInfo()
00061 
00062     manage_options = (
00063         { 'label' : 'Workflows', 'action' : 'manage_main'},
00064     )
00065 
00066     #
00067     #   ZMI methods
00068     #
00069 
00070     security.declareProtected( ManagePortal, '_manage_workflows' )
00071     _manage_workflows = PageTemplateFile(path_join('www', 'define_local_workflow_policy'),
00072                                               globals(),
00073                                               __name__= 'manage_main')
00074 
00075     def __init__(self, id):
00076         self.id = id
00077         self.title = ''
00078         self.description = ''
00079 
00080     security.declareProtected( ManagePortal, 'getId')
00081     def getId(self):
00082         """ Return the id
00083         """
00084         return self.id
00085 
00086     security.declareProtected( ManagePortal, 'getTitle')
00087     def getTitle(self):
00088         """ Return the title
00089         """
00090         title = getattr(self, 'title', '')
00091         return title
00092 
00093     security.declareProtected( ManagePortal, 'getDescription')
00094     def getDescription(self):
00095         """ Return the description
00096         """
00097         description = getattr(self, 'description', '')
00098         return description
00099 
00100     security.declareProtected( ManagePortal, 'setTitle')
00101     def setTitle(self, title):
00102         """ Set the title
00103         """
00104         self.title=title
00105 
00106     security.declareProtected( ManagePortal, 'setDescription')
00107     def setDescription(self, description):
00108         """ Set the description
00109         """
00110         self.description = description
00111 
00112     security.declareProtected( ManagePortal, 'manage_main')
00113     def manage_main(self, REQUEST, manage_tabs_message=None):
00114         """ Show a management screen for changing type to workflow connections
00115 
00116         Display 'None' if there's no chain for a type.
00117         """
00118         cbt = self._chains_by_type
00119         ti = self._listTypeInfo()
00120         types_info = []
00121         for t in ti:
00122             id = t.getId()
00123             title = t.Title()
00124             if title == id:
00125                 title = None
00126 
00127             if cbt is not None and cbt.has_key(id):
00128                 chain = ', '.join(cbt[id])
00129             else:
00130                 chain = 'None'
00131 
00132             types_info.append({
00133                 'id': id,
00134                 'title': title,
00135                 'chain': chain,
00136                 #'cbt': repr(cbt.get(id)), # for debug purpose
00137             })
00138         return self._manage_workflows(
00139             REQUEST,
00140             default_chain=', '.join(self._default_chain or ()),
00141             types_info=types_info,
00142             management_view='Workflows',
00143             manage_tabs_message=manage_tabs_message)
00144 
00145 
00146     security.declareProtected( ManagePortal, 'manage_changeWorkflows')
00147     def manage_changeWorkflows(self, title, description, default_chain, props=None, REQUEST=None):
00148         """ Changes which workflows apply to objects of which type
00149 
00150         A chain equal to 'None' is empty we remove the entry.
00151         """
00152         self.title = title
00153         self.description = description
00154 
00155         wf_tool = getToolByName(self, 'portal_workflow')
00156 
00157         if props is None:
00158             props = REQUEST
00159         cbt = self._chains_by_type
00160         if cbt is None:
00161             self._chains_by_type = cbt = PersistentMapping()
00162         ti = self._listTypeInfo()
00163         # Set up the chains by type.
00164         for t in ti:
00165             id = t.getId()
00166             field_name = 'chain_%s' % id
00167             chain = props.get(field_name, DEFAULT_CHAIN).strip()
00168 
00169             if chain == 'None':
00170                 if cbt.get(id, _MARKER) is not _MARKER:
00171                     self.delChain(id)
00172                 continue
00173 
00174             self.setChain(id, chain)
00175 
00176         # Set up the default chain.
00177         self.setDefaultChain(default_chain)
00178         if REQUEST is not None:
00179             return self.manage_main(REQUEST, manage_tabs_message='Changed.')
00180     manage_changeWorkflows = postonly(manage_changeWorkflows)
00181 
00182     security.declareProtected( ManagePortal, 'setChainForPortalTypes')
00183     def setChainForPortalTypes(self, pt_names, chain, REQUEST=None):
00184         """ Set a chain for portal types.
00185         """
00186         for portal_type in pt_names:
00187             self.setChain(portal_type, chain)
00188     setChainForPortalTypes = postonly(setChainForPortalTypes)
00189 
00190     security.declareProtected( ManagePortal, 'getChainFor')
00191     def getChainFor(self, ob, managescreen=False):
00192         """Returns the chain that applies to the object.
00193 
00194         If chain doesn't exist we return None to get a fallback from portal_workflow.
00195         We never return emtpy tuple that is good value for a chain.
00196         """
00197 
00198         cbt = self._chains_by_type
00199         if type(ob) == type(''):
00200             pt = ob
00201         elif hasattr(aq_base(ob), '_getPortalTypeName'):
00202             pt = ob._getPortalTypeName()
00203         else:
00204             pt = None
00205 
00206         if pt is None:
00207             return None
00208 
00209         chain = None
00210         if cbt is not None:
00211             chain = cbt.get(pt, _MARKER)
00212 
00213         # Backwards compatibility: before chain was a string, not a list
00214         if chain is not _MARKER and type(chain) == type(''):
00215             chain = map( lambda x: x.strip(), chain.split(',') )
00216 
00217         Log(LOG_DEBUG, 'Chain founded in policy', chain)
00218         if chain is _MARKER or chain is None:
00219             return None
00220         elif len(chain) == 1 and chain[0] == DEFAULT_CHAIN:
00221             default = self.getDefaultChain(ob)
00222             if default:
00223                 if managescreen:
00224                     return chain[0]
00225                 else:
00226                     return default
00227             else:
00228                 return None
00229 
00230         return chain
00231 
00232     security.declareProtected( ManagePortal, 'setDefaultChain')
00233     def setDefaultChain(self, default_chain, REQUEST=None):
00234 
00235         """ Sets the default chain for this tool. """
00236         wftool = getToolByName(self, 'portal_workflow')
00237 
00238         if type(default_chain) is type(''):
00239             default_chain = map( lambda x: x.strip(), default_chain.split(',') )
00240         ids = []
00241         for wf_id in default_chain:
00242             if wf_id:
00243                 if not wftool.getWorkflowById(wf_id):
00244                     raise ValueError, ("'%s' is not a workflow ID.\nchain: %s" % (
00245                         wf_id, repr(chain)))
00246                 ids.append(wf_id)
00247 
00248         self._default_chain = tuple(ids)
00249     setDefaultChain = postonly(setDefaultChain)
00250 
00251     security.declareProtected( ManagePortal, 'getDefaultChain')
00252     def getDefaultChain(self, ob):
00253         """ Returns the default chain."""
00254         if self._default_chain is None:
00255             wf_tool = getToolByName(self, 'portal_workflow')
00256             return wf_tool.getDefaultChainFor(ob)
00257         else:
00258             return self._default_chain
00259 
00260     security.declareProtected( ManagePortal, 'setChain')
00261     def setChain(self, portal_type, chain, REQUEST=None):
00262         """Set the chain for a portal type."""
00263         # Verify input data
00264         if portal_type not in [pt.id for pt in self._listTypeInfo()]:
00265             raise ValueError, ("'%s' is not a valid portal type." % portal_type)
00266 
00267         if type(chain) is type(''):
00268             chain = map( lambda x: x.strip(), chain.split(',') )
00269 
00270         wftool = getToolByName(self, 'portal_workflow')
00271         cbt = self._chains_by_type
00272         if cbt is None:
00273             self._chains_by_type = cbt = PersistentMapping()
00274 
00275         # if chain is None or default, we remove the entry
00276         if chain is None and cbt.has_key(portal_type):
00277             del cbt[portal_type]
00278         elif len(chain) == 1 and chain[0] == DEFAULT_CHAIN:
00279             cbt[portal_type] = chain
00280         else:
00281             for wf_id in chain:
00282                 if wf_id != '' and not wftool.getWorkflowById(wf_id):
00283                     raise ValueError, ("'%s' is not a workflow ID.\nchain: %s" % (
00284                         wf_id, repr(chain)))
00285             cbt[portal_type] = tuple(chain)
00286     setChain = postonly(setChain)
00287 
00288     security.declareProtected( ManagePortal, 'delChain')
00289     def delChain(self, portal_type, REQUEST=None):
00290         """Delete the chain for a portal type."""
00291         if self._chains_by_type.has_key(portal_type):
00292             del self._chains_by_type[portal_type]
00293     delChain = postonly(delChain)
00294 
00295     #
00296     #   Helper methods
00297     #
00298     security.declarePrivate( '_listTypeInfo' )
00299     def _listTypeInfo(self):
00300 
00301         """ List the portal types which are available.
00302         """
00303         pt = getToolByName(self, 'portal_types', None)
00304         if pt is None:
00305             return ()
00306         else:
00307             return pt.listTypeInfo()
00308 
00309 
00310 InitializeClass(DefaultWorkflowPolicyDefinition)
00311 
00312 addWorkflowPolicyFactory(DefaultWorkflowPolicyDefinition, title='Simple Policy')
00313