def DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None): ''' Private method. Puts object in a new state. ''' sci = None econtext = None moved_exc = None validation_exc = None # Figure out the old and new states. old_state = self._getWorkflowStateOf(ob, True) if tdef is None: new_state = self.initial_state if not new_state: # Do nothing if there is no initial state. We may want to create # workflows with no state at all, only for worklists. return former_status = {} else: new_state = tdef.new_state_id or old_state former_status = self._getStatusOf(ob) old_sdef = self.states[old_state] try: new_sdef = self.states[new_state] except KeyError: raise WorkflowException('Destination state undefined: ' + new_state) # Execute the "before" script. before_script_success = 1 if tdef is not None and tdef.script_name: script = self.scripts[tdef.script_name] # Pass lots of info to the script in a single parameter. sci = StateChangeInfo( ob, self, former_status, tdef, old_sdef, new_sdef, kwargs) try: #LOG('_executeTransition', 0, "script = %s, sci = %s" % (repr(script), repr(sci))) script(sci) # May throw an exception. except ValidationFailed, validation_exc: before_script_success = 0 before_script_error_message = deepcopy(validation_exc.msg) validation_exc_traceback = sys.exc_traceback except ObjectMoved, moved_exc: ob = moved_exc.getNewObject()
def _executeMetaTransition(self, ob, new_state_id): """ Allow jumping from state to another without triggering any hooks. Must be used only under certain conditions. """ sci = None econtext = None tdef = None kwargs = None # Figure out the old and new states. old_sdef = self._getWorkflowStateOf(ob) if old_sdef is None: old_state = self._getWorkflowStateOf(ob, id_only=True) else: old_state = old_sdef.getId() if old_state == new_state_id: # Object is already in expected state return former_status = self._getStatusOf(ob) new_sdef = self.states.get(new_state_id, None) if new_sdef is None: raise WorkflowException, ('Destination state undefined: ' + new_state_id) # Update variables. state_values = new_sdef.var_values if state_values is None: state_values = {} tdef_exprs = {} status = {} for id, vdef in self.variables.items(): if not vdef.for_status: continue expr = None if state_values.has_key(id): value = state_values[id] elif tdef_exprs.has_key(id): expr = tdef_exprs[id] elif not vdef.update_always and former_status.has_key(id): # Preserve former value value = former_status[id] else: if vdef.default_expr is not None: expr = vdef.default_expr else: value = vdef.default_value if expr is not None: # Evaluate an expression. if econtext is None: # Lazily create the expression context. if sci is None: sci = StateChangeInfo(ob, self, former_status, tdef, old_sdef, new_sdef, kwargs) econtext = createExprContext(sci) value = expr(econtext) status[id] = value status['comment'] = 'Jump from %r to %r' % ( old_state, new_state_id, ) status[self.state_var] = new_state_id tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) # Update role to permission assignments. self.updateRoleMappingsFor(ob) return new_sdef
def DCWorkflowDefinition_getWorklistVariableMatchDict(self, info, check_guard=True): """ Return a dict which has an entry per worklist definition (worklist id as key) and which value is a dict composed of variable matches. """ if not self.worklists: return None portal = self.getPortalObject() def getPortalTypeListForWorkflow(workflow_id): workflow_tool = portal.portal_workflow result = [] append = result.append for type_info in workflow_tool._listTypeInfo(): portal_type = type_info.id if workflow_id in workflow_tool.getChainFor(portal_type): append(portal_type) return result _getPortalTypeListForWorkflow = CachingMethod( getPortalTypeListForWorkflow, id='_getPortalTypeListForWorkflow', cache_factory='erp5_ui_long') portal_type_list = _getPortalTypeListForWorkflow(self.id) if not portal_type_list: return None variable_match_dict = {} security_manager = getSecurityManager() workflow_id = self.id workflow_title = self.title for worklist_id, worklist_definition in self.worklists.items(): action_box_name = worklist_definition.actbox_name guard = worklist_definition.guard if action_box_name: variable_match = {} for key in worklist_definition.getVarMatchKeys(): var = worklist_definition.getVarMatch(key) if isinstance(var, Expression): evaluated_value = var( createExprContext( StateChangeInfo(portal, self, kwargs=info.__dict__.copy()))) if isinstance(evaluated_value, (str, int, long)): evaluated_value = [str(evaluated_value)] else: evaluated_value = [x % info for x in var] variable_match[key] = evaluated_value if 'portal_type' in variable_match and len( variable_match['portal_type']): portal_type_intersection = set(variable_match['portal_type'])\ .intersection(portal_type_list) # in case the current workflow is not associated with portal_types # defined on the worklist, don't display the worklist for this # portal_type. variable_match['portal_type'] = list(portal_type_intersection) variable_match.setdefault('portal_type', portal_type_list) if len(variable_match.get('portal_type', [])) == 0: continue is_permitted_worklist = 0 if guard is None: is_permitted_worklist = 1 elif (not check_guard) or \ Guard_checkWithoutRoles(guard, security_manager, self, portal): is_permitted_worklist = 1 variable_match[SECURITY_PARAMETER_ID] = guard.roles if is_permitted_worklist: format_data = TemplateDict() format_data._push(info) variable_match.setdefault(SECURITY_PARAMETER_ID, ()) format_data._push(dict((k, ('&%s:list=' % k).join(v)) for\ k, v in variable_match.iteritems())) variable_match[WORKLIST_METADATA_KEY] = { 'format_data': format_data, 'worklist_title': action_box_name, 'worklist_id': worklist_id, 'workflow_title': workflow_title, 'workflow_id': workflow_id, 'action_box_url': worklist_definition.actbox_url, 'action_box_category': worklist_definition.actbox_category } variable_match_dict[worklist_id] = variable_match if len(variable_match_dict) == 0: return None return variable_match_dict
def _listGlobalActions(user=None, id=None, portal_path=None): portal = self._getPortalRoot() portal_url = portal.portal_url portal_url = portal_url() sm = getSecurityManager() res = [] fmt_data = None # We want to display some actions depending on the current date # So, we can now put this kind of expression : <= "%(now)s" # May be this patch should be moved to listFilteredActions in the future info.now = DateTime() for id, qdef in self.worklists.items(): if qdef.actbox_name: guard = qdef.guard # Patch for ERP5 by JP Smets in order # to take into account the expression of the guard # and nothing else - ERP5Workflow definitely needed some day if guard is None or Guard_checkWithoutRoles( guard, sm, self, portal): dict = {} # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles searchres_len = 0 var_match_keys = qdef.getVarMatchKeys() if var_match_keys: # Check the catalog for items in the worklist. catalog = portal.portal_catalog for k in var_match_keys: v = qdef.getVarMatch(k) if isinstance(v, Expression): v_fmt = v( createExprContext( StateChangeInfo( portal, self, kwargs=info.__dict__.copy()))) else: v_fmt = map(lambda x, info=info: x % info, v) dict[k] = v_fmt # Patch to automatically filter workflists per portal type # so that the same state can be used for different # worklists and they are not merged if not dict.has_key('portal_type'): dict['portal_type'] = portal_type_list # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles # we do not take into account the guard here if guard is not None and guard.roles: 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 if fmt_data is None: fmt_data = TemplateDict() fmt_data._push(info) fmt_data._push({'count': searchres_len}) # Patch for ERP5 by JP Smets in order to # filter per portal type more easily (ie. without # hardcoding it all) fmt_data._push({ 'portal_type': '&portal_type='.join(dict['portal_type']) }) # Patch for ERP5 by JP Smets in order # to implement worklists and search of local roles if dict.has_key('local_roles'): fmt_data._push({ 'local_roles': '&local_roles='.join(dict['local_roles']) }) else: fmt_data._push({'local_roles': ''}) res.append(( id, { 'name': qdef.actbox_name % fmt_data, 'url': '%s/%s' % (portal_url, qdef.actbox_url % fmt_data), 'worklist_id': id, 'workflow_title': self.title, 'workflow_id': self.id, 'permissions': (), # Predetermined. 'category': qdef.actbox_category })) fmt_data._pop() res.sort() return map((lambda (id, val): val), res)
elif tdef_exprs.has_key(id): expr = tdef_exprs[id] elif not vdef.update_always and former_status.has_key(id): # Preserve former value value = former_status[id] else: if vdef.default_expr is not None: expr = vdef.default_expr else: value = vdef.default_value if expr is not None: # Evaluate an expression. if econtext is None: # Lazily create the expression context. if sci is None: sci = StateChangeInfo(ob, self, former_status, tdef, old_sdef, new_sdef, kwargs) econtext = createExprContext(sci) value = expr(econtext) status[id] = value # Do not proceed in case of failure of before script if not before_script_success: status[self.state_var] = old_state # Remain in state tool = aq_parent(aq_inner(self)) tool.setStatusOf(self.id, ob, status) sci = StateChangeInfo(ob, self, status, tdef, old_sdef, new_sdef, kwargs) # put the error message in the workflow history sci.setWorkflowVariable(error_message=before_script_error_message) if validation_exc: # reraise validation failed exception