Interaction.py 9.52 KB
Newer Older
Jean-Paul Smets's avatar
Jean-Paul Smets committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
##############################################################################
#
# Copyright (c) 2003 Nexedi SARL and Contributors. All Rights Reserved.
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
# 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.
#
##############################################################################
""" Interaction in a web-configurable workflow.

$Id$
"""

from OFS.SimpleItem import SimpleItem
25
from Products.ERP5Type.Globals import DTMLFile, PersistentMapping
Jean-Paul Smets's avatar
Jean-Paul Smets committed
26
from Acquisition import aq_inner, aq_parent
27
from Products.ERP5Type import Globals
Jean-Paul Smets's avatar
Jean-Paul Smets committed
28 29
from AccessControl import ClassSecurityInfo

30
from Products.ERP5Type.Permissions import ManagePortal
Jean-Paul Smets's avatar
Jean-Paul Smets committed
31 32 33 34

from Products.DCWorkflow.ContainerTab import ContainerTab
from Products.DCWorkflow.Guard import Guard
from Products.DCWorkflow.Expression import Expression
35
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
Jean-Paul Smets's avatar
Jean-Paul Smets committed
36 37

from Products.ERP5 import _dtmldir
38
from Products.ERP5Type.Base import _aq_reset
Jean-Paul Smets's avatar
Jean-Paul Smets committed
39 40 41 42 43 44 45 46 47 48

class InteractionDefinition (SimpleItem):
    meta_type = 'Workflow Interaction'

    security = ClassSecurityInfo()
    security.declareObjectProtected(ManagePortal)

    title = ''
    description = ''
    new_state_id = ''
Jean-Paul Smets's avatar
Jean-Paul Smets committed
49
    trigger_type = TRIGGER_WORKFLOW_METHOD
Jean-Paul Smets's avatar
Jean-Paul Smets committed
50 51 52 53 54
    guard = None
    actbox_name = ''
    actbox_url = ''
    actbox_category = 'workflow'
    var_exprs = None  # A mapping.
Jean-Paul Smets's avatar
Jean-Paul Smets committed
55 56
    script_name = ()  # Executed before transition
    after_script_name = ()  # Executed after transition
57
    before_commit_script_name = () #Executed Before Commit Transaction
Jean-Paul Smets's avatar
Jean-Paul Smets committed
58
    activate_script_name = ()  # Executed as activity
59 60
    method_id = ()
    portal_type_filter = None
61
    once_per_transaction = False
Jean-Paul Smets's avatar
Jean-Paul Smets committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

    manage_options = (
        {'label': 'Properties', 'action': 'manage_properties'},
        {'label': 'Variables', 'action': 'manage_variables'},
        )

    def __init__(self, id):
        self.id = id

    def getId(self):
        return self.id

    def getGuardSummary(self):
        res = None
        if self.guard is not None:
            res = self.guard.getSummary()
        return res

    def getGuard(self):
        if self.guard is not None:
            return self.guard
        else:
            return Guard().__of__(self)  # Create a temporary guard.

    def getVarExprText(self, id):
        if not self.var_exprs:
            return ''
        else:
            expr = self.var_exprs.get(id, None)
            if expr is not None:
                return expr.text
            else:
                return ''

    def getWorkflow(self):
        return aq_parent(aq_inner(aq_parent(aq_inner(self))))

    def getAvailableStateIds(self):
        return self.getWorkflow().states.keys()

    def getAvailableScriptIds(self):
        return self.getWorkflow().scripts.keys()

    def getAvailableVarIds(self):
        return self.getWorkflow().variables.keys()

    _properties_form = DTMLFile('interaction_properties', _dtmldir)

    def manage_properties(self, REQUEST, manage_tabs_message=None):
        '''
        '''
        return self._properties_form(REQUEST,
                                     management_view='Properties',
                                     manage_tabs_message=manage_tabs_message,
                                     )

Jean-Paul Smets's avatar
Jean-Paul Smets committed
118 119
    def setProperties(self, title,
                      portal_type_filter=None,
120
                      trigger_type=TRIGGER_WORKFLOW_METHOD,
121
                      once_per_transaction=False,
Jean-Paul Smets's avatar
Jean-Paul Smets committed
122 123
                      script_name=(),
                      after_script_name=(),
124
                      before_commit_script_name=(),
Jean-Paul Smets's avatar
Jean-Paul Smets committed
125
                      activate_script_name=(),
Jean-Paul Smets's avatar
Jean-Paul Smets committed
126 127
                      actbox_name='', actbox_url='',
                      actbox_category='workflow',
128
                      method_id=(),
Jean-Paul Smets's avatar
Jean-Paul Smets committed
129
                      props=None, REQUEST=None, description=''):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
130
        """
Jean-Paul Smets's avatar
Jean-Paul Smets committed
131 132 133
          Update transition properties
          XXX - then make sure that method_id is WorkflowMethod for portal_type_filter
          XXX - this will likely require dynamic
Jean-Paul Smets's avatar
Jean-Paul Smets committed
134
        """
135 136 137 138
        if type(method_id) is type(''):
            self.method_id = method_id.split()
        else:
            self.method_id = method_id
139 140 141 142 143 144 145 146
        if portal_type_filter is not None and 'None' in portal_type_filter:
          portal_type_filter = None
        if 'None' in after_script_name:
          after_script_name = ()
        if 'None' in activate_script_name:
          activate_script_name = ()
        if 'None' in script_name:
          script_name = ()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
147
        self.portal_type_filter = portal_type_filter
Jean-Paul Smets's avatar
Jean-Paul Smets committed
148 149 150
        self.title = str(title)
        self.description = str(description)
        self.trigger_type = int(trigger_type)
151
        self.once_per_transaction = bool(once_per_transaction)
152 153
        self.script_name = script_name
        self.after_script_name = after_script_name
154
        self.before_commit_script_name = before_commit_script_name
155
        self.activate_script_name = activate_script_name
Jean-Paul Smets's avatar
Jean-Paul Smets committed
156 157 158 159 160 161 162 163
        g = Guard()
        if g.changeFromProperties(props or REQUEST):
            self.guard = g
        else:
            self.guard = None
        self.actbox_name = str(actbox_name)
        self.actbox_url = str(actbox_url)
        self.actbox_category = str(actbox_category)
164 165
        # reset _aq_dynamic method cache.
        _aq_reset()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
        if REQUEST is not None:
            return self.manage_properties(REQUEST, 'Properties changed.')

    _variables_form = DTMLFile('interaction_variables', _dtmldir)

    def manage_variables(self, REQUEST, manage_tabs_message=None):
        '''
        '''
        return self._variables_form(REQUEST,
                                     management_view='Variables',
                                     manage_tabs_message=manage_tabs_message,
                                     )

    def getVariableExprs(self):
        ''' get variable exprs for management UI
        '''
        ve = self.var_exprs
        if ve is None:
            return []
        else:
            ret = []
            for key in ve.keys():
                ret.append((key,self.getVarExprText(key)))
            return ret
    
    def getWorkflowVariables(self):
        ''' get all variables that are available form
            workflow and not handled yet.
        '''
        wf_vars = self.getAvailableVarIds()
        if self.var_exprs is None:
                return wf_vars
        ret = []
        for vid in wf_vars:
            if not self.var_exprs.has_key(vid):
                ret.append(vid)
        return ret

    def addVariable(self, id, text, REQUEST=None):
        '''
        Add a variable expression.
        '''
        if self.var_exprs is None:
            self.var_exprs = PersistentMapping()
        
        expr = None
        if text:
          expr = Expression(str(text))
        self.var_exprs[id] = expr
        
        if REQUEST is not None:
            return self.manage_variables(REQUEST, 'Variable added.')
    
    def deleteVariables(self,ids=[],REQUEST=None):
        ''' delete a WorkflowVariable from State
        '''
        ve = self.var_exprs
        for id in ids:
            if ve.has_key(id):
                del ve[id]
                
        if REQUEST is not None:
            return self.manage_variables(REQUEST, 'Variables deleted.')

    def setVariables(self, ids=[], REQUEST=None):
        ''' set values for Variables set by this state
        '''
        if self.var_exprs is None:
            self.var_exprs = PersistentMapping()
 
        ve = self.var_exprs
 
        if REQUEST is not None:
            for id in ve.keys():
                fname = 'varexpr_%s' % id

                val = REQUEST[fname]
                expr = None
                if val:
                    expr = Expression(str(REQUEST[fname]))
                ve[id] = expr

            return self.manage_variables(REQUEST, 'Variables changed.')

Globals.InitializeClass(InteractionDefinition)


class Interaction (ContainerTab):

    meta_type = 'Workflow Interaction'

    security = ClassSecurityInfo()
    security.declareObjectProtected(ManagePortal)

    all_meta_types = ({'name':InteractionDefinition.meta_type,
                       'action':'addInteraction',
262
                       'permission': 'Manage portal',
Jean-Paul Smets's avatar
Jean-Paul Smets committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
                       },)

    _manage_interaction = DTMLFile('interactions', _dtmldir)

    def manage_main(self, REQUEST, manage_tabs_message=None):
        '''
        '''
        return self._manage_interaction(
            REQUEST,
            management_view='Interactions',
            manage_tabs_message=manage_tabs_message,
            )

    def addInteraction(self, id, REQUEST=None):
        '''
        '''
        tdef = InteractionDefinition(id)
        self._setObject(id, tdef)
        if REQUEST is not None:
            return self.manage_main(REQUEST, 'Interaction added.')

    def deleteInteractions(self, ids, REQUEST=None):
        '''
        '''
        for id in ids:
            self._delObject(id)
        if REQUEST is not None:
            return self.manage_main(REQUEST, 'Interaction(s) removed.')

Globals.InitializeClass(Interaction)