def manage_addActionForm(self): """Form for adding a new CMF Action object. """ profiles = [] stool = getToolByName(self, 'portal_setup', None) if stool: for info in stool.listContextInfos(): action_paths = [] context = stool._getImportContext(info['id']) body = context.readDataFile('actions.xml') if body is None: continue root = parseString(body).documentElement for node in root.childNodes: if node.nodeName != 'object': continue action_paths += _extractChildren(node) action_paths.sort() profiles.append({ 'id': info['id'], 'title': info['title'], 'action_paths': tuple(action_paths) }) template = PageTemplateResource('www/addAction.zpt', globals()).__of__(self) return template(profiles=tuple(profiles))
def addConfiguredSiteForm(dispatcher): """ Wrap the PTF in 'dispatcher', including 'profile_registry' in options. """ wrapped = PageTemplateResource( 'www/siteAddForm.zpt', globals() ).__of__( dispatcher ) base_profiles = [] extension_profiles = [] for info in profile_registry.listProfileInfo(): if info.get('type') == EXTENSION: extension_profiles.append(info) else: base_profiles.append(info) return wrapped( base_profiles=tuple(base_profiles), extension_profiles =tuple(extension_profiles) )
class CalendarTool (UniqueObject, SimpleItem): """ a calendar tool for encapsualting how calendars work and are displayed """ id = 'portal_calendar' meta_type= 'CMF Calendar Tool' security = ClassSecurityInfo() calendar_types = ('Event',) calendar_states = ('published',) use_session = '' manage_options = ( ({ 'label' : 'Overview', 'action' : 'manage_overview' } , { 'label' : 'Configure', 'action' : 'manage_configure' } , ) + SimpleItem.manage_options ) # # ZMI methods # security.declareProtected( ManagePortal, 'manage_overview' ) manage_overview = PageTemplateResource( 'www/explainCalendarTool.zpt' , globals() , __name__='manage_overview' ) security.declareProtected( ManagePortal, 'manage_configure' ) manage_configure = PageTemplateResource( 'www/configureCalendarTool.zpt' , globals() , __name__='manage_configure' ) security.declareProtected( ManagePortal, 'edit_configuration' ) def edit_configuration(self, show_types, use_session, show_states=None): """ Change the configuration of the calendar tool """ self.calendar_types = tuple(show_types) self.use_session = use_session if show_states is not None: self.calendar_states = tuple(show_states) if hasattr(self.REQUEST, 'RESPONSE'): self.REQUEST.RESPONSE.redirect('manage_configure') security.declarePublic('getCalendarTypes') def getCalendarTypes(self): """ Returns a list of type that will show in the calendar """ return self.calendar_types security.declarePublic('getCalendarStates') def getCalendarStates(self): """ Returns a list of workflow states that will show in the calendar """ return self.calendar_states security.declarePublic('getUseSession') def getUseSession(self): """ Returns the Use_Session option """ return self.use_session security.declarePublic('getDays') def getDays(self): """ Returns a list of days with the correct start day first """ return calendar.weekheader(2).split() security.declarePublic('getWeeksList') def getWeeksList(self, month='1', year='2002'): """Creates a series of weeks, each of which contains an integer day number. A day number of 0 means that day is in the previous or next month. """ year=int(year) month=int(month) # daysByWeek is a list of days inside a list of weeks, like so: # [[0, 1, 2, 3, 4, 5, 6], # [7, 8, 9, 10, 11, 12, 13], # [14, 15, 16, 17, 18, 19, 20], # [21, 22, 23, 24, 25, 26, 27], # [28, 29, 30, 31, 0, 0, 0]] daysByWeek=calendar.monthcalendar(year, month) return daysByWeek security.declarePublic('getEventsForCalendar') def getEventsForCalendar(self, month='1', year='2002'): """ recreates a sequence of weeks, by days each day is a mapping. {'day': #, 'url': None} """ year=int(year) month=int(month) # daysByWeek is a list of days inside a list of weeks, like so: # [[0, 1, 2, 3, 4, 5, 6], # [7, 8, 9, 10, 11, 12, 13], # [14, 15, 16, 17, 18, 19, 20], # [21, 22, 23, 24, 25, 26, 27], # [28, 29, 30, 31, 0, 0, 0]] daysByWeek=calendar.monthcalendar(year, month) weeks=[] events=self.catalog_getevents(year, month) for week in daysByWeek: days=[] for day in week: if events.has_key(day): days.append(events[day]) else: days.append({'day': day, 'event': 0, 'eventslist':[]}) weeks.append(days) return weeks security.declarePublic('catalog_getevents') def catalog_getevents(self, year, month): """ given a year and month return a list of days that have events """ year=int(year) month=int(month) last_day=calendar.monthrange(year, month)[1] first_date=self.getBeginAndEndTimes(1, month, year)[0] last_date=self.getBeginAndEndTimes(last_day, month, year)[1] query = self.portal_catalog( portal_type=self.getCalendarTypes(), review_state=self.getCalendarStates(), start={'query': last_date, 'range': 'max'}, end={'query': first_date, 'range': 'min'}, sort_on='start' ) # compile a list of the days that have events eventDays={} for daynumber in range(1, 32): # 1 to 31 eventDays[daynumber] = {'eventslist':[], 'event':0, 'day':daynumber} includedevents = [] for result in query: if result.getRID() in includedevents: break else: includedevents.append(result.getRID()) event={} # we need to deal with events that end next month if result.end.month() != month: # doesn't work for events that last ~12 months # fix it if it's a problem, otherwise ignore eventEndDay = last_day event['end'] = None else: eventEndDay = result.end.day() event['end'] = result.end.Time() # and events that started last month if result.start.month() != month: # same as above re: 12 month thing eventStartDay = 1 event['start'] = None else: eventStartDay = result.start.day() event['start'] = result.start.Time() event['title'] = result.Title or result.getId if eventStartDay != eventEndDay: allEventDays = range(eventStartDay, eventEndDay+1) eventDays[eventStartDay]['eventslist'].append( {'end': None, 'start': result.start.Time(), 'title': event['title']} ) eventDays[eventStartDay]['event'] = 1 for eventday in allEventDays[1:-1]: eventDays[eventday]['eventslist'].append( {'end': None, 'start': None, 'title': event['title']} ) eventDays[eventday]['event'] = 1 if result.end == result.end.earliestTime(): last_day = eventDays[allEventDays[-2]] last_days_event = last_day['eventslist'][-1] last_days_event['end'] = (result.end-1).latestTime().Time() else: eventDays[eventEndDay]['eventslist'].append( {'end': result.end.Time(), 'start': None, 'title': event['title']} ) eventDays[eventEndDay]['event'] = 1 else: eventDays[eventStartDay]['eventslist'].append(event) eventDays[eventStartDay]['event'] = 1 # This list is not uniqued and isn't sorted # uniquing and sorting only wastes time # and in this example we don't need to because # later we are going to do an 'if 2 in eventDays' # so the order is not important. # example: [23, 28, 29, 30, 31, 23] return eventDays security.declarePublic('getEventsForThisDay') def getEventsForThisDay(self, thisDay): """ given an exact day return ALL events that: A) Start on this day OR B) End on this day OR C) Start before this day AND end after this day""" catalog = self.portal_catalog day, month, year = ( int(thisDay.day()) , int(thisDay.month()) , int(thisDay.year()) ) first_date, last_date = self.getBeginAndEndTimes(day, month, year) zone = first_date.localZone() after_midnight_str = '%d-%02d-%02d 00:01:00 %s' % (year,month,day,zone) after_midnight = DateTime(after_midnight_str) # Get all events that Start on this day query = self.portal_catalog( portal_type=self.getCalendarTypes(), review_state=self.getCalendarStates(), start={'query': (first_date, last_date), 'range': 'minmax'} ) # Get all events that End on this day query += self.portal_catalog( portal_type=self.getCalendarTypes(), review_state=self.getCalendarStates(), end={'query': (after_midnight, last_date), 'range': 'minmax'} ) # Get all events that Start before this day AND End after this day query += self.portal_catalog( portal_type=self.getCalendarTypes(), review_state=self.getCalendarStates(), start={'query': first_date, 'range': 'max'}, end={'query': last_date, 'range': 'min'} ) # Unique the results results = [] rids = [] for item in query: rid = item.getRID() if not rid in rids: results.append(item) rids.append(rid) def sort_function(x,y): z = cmp(x.start,y.start) if not z: return cmp(x.end,y.end) return z # Sort by start date results.sort(sort_function) return results security.declarePublic('getPreviousMonth') def getPreviousMonth(self, month, year): # given any particular year and month, this method will return a # datetime object for one month prior try: month=int(month) except: raise "Calendar Type Error", month try: year=int(year) except: raise "Calendar Type Error", year if month==0 or month==1: month, year = 12, year - 1 else: month-=1 return DateTime(year, month, 1) security.declarePublic('getNextMonth') def getNextMonth(self, month, year): # given any particular year and month, this method will return a datetime object # for one month after try: month=int(month) except: raise "Calendar Type Error", month try: year=int(year) except: raise "Calendar Type Error", year if month==12: month, year = 1, year + 1 else: month+=1 return DateTime(year, month, 1) security.declarePublic('getBeginAndEndTimes') def getBeginAndEndTimes(self, day, month, year): # Given any day, month and year this method returns 2 DateTime objects # That represent the exact start and the exact end of that particular day. day=int(day) month=int(month) year=int(year) begin=DateTime('%d-%02d-%02d 00:00:00' % (year, month, day)) end=DateTime('%d-%02d-%02d 23:59:59' % (year, month, day)) return (begin, end)
class WorkflowUIMixin: ''' ''' security = ClassSecurityInfo() security.declareProtected(ManagePortal, 'manage_properties') manage_properties = DTMLResource('dtml/workflow_properties', globals()) manage_groups = PageTemplateResource('dtml/workflow_groups.pt', globals()) security.declareProtected(ManagePortal, 'setProperties') def setProperties(self, title, manager_bypass=0, props=None, REQUEST=None): """Sets basic properties. """ self.title = str(title) self.manager_bypass = manager_bypass and 1 or 0 g = Guard() if g.changeFromProperties(props or REQUEST): self.creation_guard = g else: self.creation_guard = None if REQUEST is not None: return self.manage_properties( REQUEST, manage_tabs_message='Properties changed.') _permissions_form = DTMLResource('dtml/workflow_permissions', globals()) security.declareProtected(ManagePortal, 'manage_permissions') def manage_permissions(self, REQUEST, manage_tabs_message=None): """Displays the form for choosing which permissions to manage. """ return self._permissions_form(REQUEST, management_view='Permissions', manage_tabs_message=manage_tabs_message, ) security.declareProtected(ManagePortal, 'addManagedPermission') def addManagedPermission(self, p, REQUEST=None): """Adds to the list of permissions to manage. """ if p in self.permissions: raise ValueError, 'Already a managed permission: ' + p if REQUEST is not None and p not in self.getPossiblePermissions(): raise ValueError, 'Not a valid permission name:' + p self.permissions = self.permissions + (p,) if REQUEST is not None: return self.manage_permissions( REQUEST, manage_tabs_message='Permission added.') security.declareProtected(ManagePortal, 'delManagedPermissions') def delManagedPermissions(self, ps, REQUEST=None): """Removes from the list of permissions to manage. """ if ps: l = list(self.permissions) for p in ps: l.remove(p) self.permissions = tuple(l) if REQUEST is not None: return self.manage_permissions( REQUEST, manage_tabs_message='Permission(s) removed.') security.declareProtected(ManagePortal, 'getPossiblePermissions') def getPossiblePermissions(self): """Returns the list of all permissions that can be managed. """ # possible_permissions is in AccessControl.Role.RoleManager. return list(self.possible_permissions()) security.declareProtected(ManagePortal, 'getGroups') def getGroups(self): """Returns the names of groups managed by this workflow. """ return tuple(self.groups) security.declareProtected(ManagePortal, 'getAvailableGroups') def getAvailableGroups(self): """Returns a list of available group names. """ gf = aq_get( self, '__allow_groups__', None, 1 ) if gf is None: return () try: groups = gf.searchGroups() except AttributeError: return () else: return [g['id'] for g in groups] security.declareProtected(ManagePortal, 'addGroup') def addGroup(self, group, RESPONSE=None): """Adds a group by name. """ if group not in self.getAvailableGroups(): raise ValueError(group) self.groups = self.groups + (group,) if RESPONSE is not None: RESPONSE.redirect( "%s/manage_groups?manage_tabs_message=Added+group." % self.absolute_url()) security.declareProtected(ManagePortal, 'delGroups') def delGroups(self, groups, RESPONSE=None): """Removes groups by name. """ self.groups = tuple([g for g in self.groups if g not in groups]) if RESPONSE is not None: RESPONSE.redirect( "%s/manage_groups?manage_tabs_message=Groups+removed." % self.absolute_url()) security.declareProtected(ManagePortal, 'getAvailableRoles') def getAvailableRoles(self): """Returns the acquired roles mixed with base_cms roles. """ roles = list(self.valid_roles()) for role in getDefaultRolePermissionMap().keys(): if role not in roles: roles.append(role) roles.sort() return roles security.declareProtected(ManagePortal, 'getRoles') def getRoles(self): """Returns the list of roles managed by this workflow. """ roles = self.roles if roles is not None: return roles roles = getDefaultRolePermissionMap().keys() if roles: # Map the base_cms roles by default. roles.sort() return roles return self.valid_roles() security.declareProtected(ManagePortal, 'setRoles') def setRoles(self, roles, RESPONSE=None): """Changes the list of roles mapped to groups by this workflow. """ avail = self.getAvailableRoles() for role in roles: if role not in avail: raise ValueError(role) self.roles = tuple(roles) if RESPONSE is not None: RESPONSE.redirect( "%s/manage_groups?manage_tabs_message=Roles+changed." % self.absolute_url()) security.declareProtected(ManagePortal, 'getGuard') def getGuard(self): """Returns the initiation guard. If no init guard has been created, returns a temporary object. """ if self.creation_guard is not None: return self.creation_guard else: return Guard().__of__(self) # Create a temporary guard. security.declarePublic('guardExprDocs') def guardExprDocs(self): """Returns documentation on guard expressions. """ text = resource_string('doc/expressions.stx', globals()) from DocumentTemplate.DT_Var import structured_text return structured_text(text)
class WorkflowDefinitionConfigurator(Implicit): """ Synthesize XML description of site's workflows. """ security = ClassSecurityInfo() def __init__(self, site): self._site = site security.declareProtected(ManagePortal, 'getWorkflowInfo') def getWorkflowInfo(self, workflow_id): """ Return a mapping describing a given workflow. o Keys in the mappings: 'id' -- the ID of the workflow within the tool 'meta_type' -- the workflow's meta_type 'title' -- the workflow's title property o See '_extractDCWorkflowInfo' below for keys present only for DCWorkflow definitions. """ workflow_tool = getToolByName(self._site, 'portal_workflow') workflow = workflow_tool.getWorkflowById(workflow_id) workflow_info = { 'id': workflow_id, 'meta_type': workflow.meta_type, 'title': workflow.title_or_id() } if workflow.meta_type == DCWorkflowDefinition.meta_type: self._extractDCWorkflowInfo(workflow, workflow_info) return workflow_info security.declareProtected(ManagePortal, 'generateWorkflowXML') def generateWorkflowXML(self, workflow_id): """ Pseudo API. """ info = self.getWorkflowInfo(workflow_id) if info['meta_type'] != DCWorkflowDefinition.meta_type: return None return self._workflowConfig(workflow_id=workflow_id) security.declareProtected(ManagePortal, 'generateWorkflowScripts') def getWorkflowScripts(self, workflow_id): """ Get workflow scripts inforation """ workflow_tool = getToolByName(self._site, 'portal_workflow') workflow = workflow_tool.getWorkflowById(workflow_id) if workflow.meta_type != DCWorkflowDefinition.meta_type: return [] scripts = self._extractScripts(workflow) return scripts security.declareProtected(ManagePortal, 'parseWorkflowXML') def parseWorkflowXML(self, xml, encoding=None): """ Pseudo API. """ dom = domParseString(xml) root = dom.getElementsByTagName('dc-workflow')[0] workflow_id = _getNodeAttribute(root, 'workflow_id', encoding) title = _getNodeAttribute(root, 'title', encoding) state_variable = _getNodeAttribute(root, 'state_variable', encoding) initial_state = _getNodeAttribute(root, 'initial_state', encoding) states = _extractStateNodes(root, encoding) transitions = _extractTransitionNodes(root, encoding) variables = _extractVariableNodes(root, encoding) worklists = _extractWorklistNodes(root, encoding) permissions = _extractPermissionNodes(root, encoding) scripts = _extractScriptNodes(root, encoding) return (workflow_id, title, state_variable, initial_state, states, transitions, variables, worklists, permissions, scripts) security.declarePrivate('_workflowConfig') _workflowConfig = PageTemplateResource('xml/wtcWorkflowExport.xml', globals(), __name__='workflowConfig') security.declarePrivate('_extractDCWorkflowInfo') def _extractDCWorkflowInfo(self, workflow, workflow_info): """ Append the information for a 'workflow' into 'workflow_info' o 'workflow' must be a DCWorkflowDefinition instance. o 'workflow_info' must be a dictionary. o The following keys will be added to 'workflow_info': 'permissions' -- a list of names of permissions managed by the workflow 'state_variable' -- the name of the workflow's "main" state variable 'initial_state' -- the name of the state in the workflow in which objects start their lifecycle. 'variable_info' -- a list of mappings describing the variables tracked by the workflow (see '_extractVariables'). 'state_info' -- a list of mappings describing the states tracked by the workflow (see '_extractStates'). 'transition_info' -- a list of mappings describing the transitions tracked by the workflow (see '_extractTransitions'). 'worklist_info' -- a list of mappings describing the worklists tracked by the workflow (see '_extractWorklists'). 'script_info' -- a list of mappings describing the scripts which provide added business logic (wee '_extractScripts'). """ workflow_info['filename'] = _getWorkflowFilename(workflow.getId()) workflow_info['state_variable'] = workflow.state_var workflow_info['initial_state'] = workflow.initial_state workflow_info['permissions'] = workflow.permissions workflow_info['variable_info'] = self._extractVariables(workflow) workflow_info['state_info'] = self._extractStates(workflow) workflow_info['transition_info'] = self._extractTransitions(workflow) workflow_info['worklist_info'] = self._extractWorklists(workflow) workflow_info['script_info'] = self._extractScripts(workflow) security.declarePrivate('_extractVariables') def _extractVariables(self, workflow): """ Return a sequence of mappings describing DCWorkflow variables. o Keys for each mapping will include: 'id' -- the variable's ID 'description' -- a textual description of the variable 'for_catalog' -- whether to catalog this variable 'for_status' -- whether to ??? this variable (XXX) 'update_always' -- whether to update this variable whenever executing a transition (xxX) 'default_value' -- a default value for the variable (XXX) 'default_expression' -- a TALES expression for the default value 'guard_permissions' -- a list of permissions guarding access to the variable 'guard_roles' -- a list of roles guarding access to the variable 'guard_groups' -- a list of groups guarding the transition 'guard_expr' -- an expression guarding access to the variable """ result = [] items = workflow.variables.objectItems() items.sort() for k, v in items: guard = v.getInfoGuard() default_type = _guessVariableType(v.default_value) info = { 'id': k, 'description': v.description, 'for_catalog': bool(v.for_catalog), 'for_status': bool(v.for_status), 'update_always': bool(v.update_always), 'default_value': v.default_value, 'default_type': default_type, 'default_expr': v.getDefaultExprText(), 'guard_permissions': guard.permissions, 'guard_roles': guard.roles, 'guard_groups': guard.groups, 'guard_expr': guard.getExprText() } result.append(info) return result security.declarePrivate('_extractStates') def _extractStates(self, workflow): """ Return a sequence of mappings describing DCWorkflow states. o Within the workflow mapping, each 'state_info' mapping has keys: 'id' -- the state's ID 'title' -- the state's title 'description' -- the state's description 'transitions' -- a list of IDs of transitions out of the state 'permissions' -- a list of mappings describing the permission map for the state 'groups' -- a list of ( group_id, (roles,) ) tuples describing the group-role assignments for the state 'variables' -- a list of mapping for the variables to be set when entering the state. o Within the state_info mappings, each 'permissions' mapping has the keys: 'name' -- the name of the permission 'roles' -- a sequence of role IDs which have the permission 'acquired' -- whether roles are acquired for the permission o Within the state_info mappings, each 'variable' mapping has the keys: 'name' -- the name of the variable 'type' -- the type of the value (allowed values are: 'string', 'datetime', 'bool', 'int') 'value' -- the value to be set """ result = [] items = workflow.states.objectItems() items.sort() for k, v in items: groups = v.group_roles and list(v.group_roles.items()) or [] groups = [x for x in groups if x[1]] groups.sort() variables = list(v.getVariableValues()) variables.sort() v_info = [] for v_name, value in variables: v_info.append({ 'name': v_name, 'type': _guessVariableType(value), 'value': value }) info = { 'id': k, 'title': v.title, 'description': v.description, 'transitions': v.transitions, 'permissions': self._extractStatePermissions(v), 'groups': groups, 'variables': v_info } result.append(info) return result security.declarePrivate('_extractStatePermissions') def _extractStatePermissions(self, state): """ Return a sequence of mappings for the permissions in a state. o Each mapping has the keys: 'name' -- the name of the permission 'roles' -- a sequence of role IDs which have the permission 'acquired' -- whether roles are acquired for the permission """ result = [] items = state.permission_roles.items() items.sort() for k, v in items: result.append({ 'name': k, 'roles': v, 'acquired': not isinstance(v, tuple) }) return result security.declarePrivate('_extractTransitions') def _extractTransitions(self, workflow): """ Return a sequence of mappings describing DCWorkflow transitions. o Each mapping has the keys: 'id' -- the transition's ID 'title' -- the transition's ID 'description' -- the transition's description 'new_state_id' -- the ID of the state into which the transition moves an object 'trigger_type' -- one of the following values, indicating how the transition is fired: - "AUTOMATIC" -> fired opportunistically whenever the workflow notices that its guard conditions permit - "USER" -> fired in response to user request 'script_name' -- the ID of a script to be executed before the transition 'after_script_name' -- the ID of a script to be executed after the transition 'actbox_name' -- the name of the action by which the user triggers the transition 'actbox_url' -- the URL of the action by which the user triggers the transition 'actbox_category' -- the category of the action by which the user triggers the transition 'variables' -- a list of ( id, expr ) tuples defining how variables are to be set during the transition 'guard_permissions' -- a list of permissions guarding the transition 'guard_roles' -- a list of roles guarding the transition 'guard_groups' -- a list of groups guarding the transition 'guard_expr' -- an expression guarding the transition """ result = [] items = workflow.transitions.objectItems() items.sort() for k, v in items: guard = v.getGuard() v_info = [] for v_name, expr in v.getVariableExprs(): v_info.append({'name': v_name, 'expr': expr}) info = { 'id': k, 'title': v.title, 'description': v.description, 'new_state_id': v.new_state_id, 'trigger_type': TRIGGER_TYPES[v.trigger_type], 'script_name': v.script_name, 'after_script_name': v.after_script_name, 'actbox_name': v.actbox_name, 'actbox_url': v.actbox_url, 'actbox_category': v.actbox_category, 'variables': v_info, 'guard_permissions': guard.permissions, 'guard_roles': guard.roles, 'guard_groups': guard.groups, 'guard_expr': guard.getExprText() } result.append(info) return result security.declarePrivate('_extractWorklists') def _extractWorklists(self, workflow): """ Return a sequence of mappings describing DCWorkflow transitions. o Each mapping has the keys: 'id' -- the ID of the worklist 'title' -- the title of the worklist 'description' -- a textual description of the worklist 'var_match' -- a list of ( key, value ) tuples defining the variables used to "activate" the worklist. 'actbox_name' -- the name of the "action" corresponding to the worklist 'actbox_url' -- the URL of the "action" corresponding to the worklist 'actbox_category' -- the category of the "action" corresponding to the worklist 'guard_permissions' -- a list of permissions guarding access to the worklist 'guard_roles' -- a list of roles guarding access to the worklist 'guard_expr' -- an expression guarding access to the worklist """ result = [] items = workflow.worklists.objectItems() items.sort() for k, v in items: guard = v.getGuard() var_match = [(id, v.getVarMatchText(id)) for id in v.getVarMatchKeys()] info = { 'id': k, 'title': v.title, 'description': v.description, 'var_match': var_match, 'actbox_name': v.actbox_name, 'actbox_url': v.actbox_url, 'actbox_category': v.actbox_category, 'guard_permissions': guard.permissions, 'guard_roles': guard.roles, 'guard_groups': guard.groups, 'guard_expr': guard.getExprText() } result.append(info) return result security.declarePrivate('_extractScripts') def _extractScripts(self, workflow): """ Return a sequence of mappings describing DCWorkflow scripts. o Each mapping has the keys: 'id' -- the ID of the script 'meta_type' -- the title of the worklist 'body' -- the text of the script 'filename' -- the name of the file to / from which the script is stored / loaded """ result = [] items = workflow.scripts.objectItems() items.sort() for k, v in items: filename = _getScriptFilename(workflow.getId(), k, v.meta_type) info = { 'id': k, 'meta_type': v.meta_type, 'body': v.read(), 'filename': filename } result.append(info) return result
def _getExportTemplate(self): return PageTemplateResource('xml/wtcToolExport.xml', globals())
""" List the actions defined in this category and its subcategories. """ actions = [] for obj in self.objectValues(): if IActionCategory.providedBy(obj): actions.extend(obj.listActions()) elif IAction.providedBy(obj): actions.append(obj) return tuple(actions) InitializeClass(ActionCategory) manage_addActionCategoryForm = PageTemplateResource( 'www/addActionCategory.zpt', globals()) def manage_addActionCategory(self, id, REQUEST=None): """Add a new CMF Action Category object with ID *id*. """ obj = ActionCategory(id) self._setObject(id, obj) if REQUEST: return self.manage_main(self, REQUEST, update_menu=1) class Action(SimpleItemWithProperties): """ Reference to an action. """
class ActionIconsTool(UniqueObject, SimpleItem): """ Map actions only icons. """ meta_type = 'Action Icons Tool' id = 'portal_actionicons' security = ClassSecurityInfo() security.declareObjectProtected(View) def __init__(self): self.clearActionIcons() # # Accessors # security.declareProtected(ManagePortal, 'listActionIcons') def listActionIcons(self): """ Return a sequence of mappings for action icons o Mappings are in the form: ( category, action ) -> icon, where category and action are strings and icon is an ActionIcon instance. """ return [x.__of__(self) for x in self._icons] security.declareProtected(View, 'getActionInfo') def getActionInfo(self, category, action_id, context=None): """ Return a tuple, '(title, priority, icon ID), for the given action. o Raise a KeyError if no icon has been defined for the action. """ ai = self._lookup[(category, action_id)] return (ai.getTitle(), ai.getPriority(), ai.getIconURL(context)) security.declareProtected(View, 'queryActionInfo') def queryActionInfo(self, category, action_id, default=None, context=None): """ Return a tuple, '(title, priority, icon ID), for the given action. o Return 'default' if no icon has been defined for the action. """ ai = self._lookup.get((category, action_id)) return ai and (ai.getTitle(), ai.getPriority(), ai.getIconURL(context)) or default security.declareProtected(View, 'getActionIcon') def getActionIcon(self, category, action_id, context=None): """ Return an icon ID for the given action. o Raise a KeyError if no icon has been defined for the action. o Context is an Expression context object, used to evaluate TALES expressions. """ return self._lookup[(category, action_id)].getIconURL(context) security.declareProtected(View, 'queryActionIcon') def queryActionIcon(self, category, action_id, default=None, context=None): """ Return an icon ID for the given action. o Return 'default' if no icon has been defined for the action. o Context is an Expression context object, used to evaluate TALES expressions. """ ai = self._lookup.get((category, action_id)) return ai and ai.getIconURL(context) or default security.declareProtected(View, 'updateActionDicts') def updateActionDicts(self, categorized_actions, context=None): """ Update a set of dictionaries, adding 'title, 'priority', and 'icon' keys. o S.b. passed a data structure like that returned from ActionsTool's 'listFilteredActionsFor': - Dict mapping category -> seq. of dicts, where each of the leaf dicts must have 'category' and 'id' keys. o *Will* overwrite the 'title' key, if title is defined on the tool. o *Will* overwrite the 'priority' key. o *Will* overwrite the 'icon' key, if icon is defined on the tool o XXX: Don't have a way to pass Expression context yet. """ result = {} for category, actions in categorized_actions.items(): new_actions = [] for action in actions: action = action.copy() action_id = action.get('id') # Hack around DCWorkflow's ID-less worklist actions. if action_id is None and action.get('category') == 'workflow': action['id'] = action_id = action.get('name') if action_id: info = self.queryActionInfo(category, action_id, context=context) if info is not None: title, priority, icon = info if title is not None: action['title'] = title if priority is not None: action['priority'] = priority if icon is not None: action['icon'] = icon new_actions.append(action) new_actions.sort( lambda x, y: cmp(x.get('priority', 0), y.get('priority', 0))) result[category] = new_actions return result __call__ = updateActionDicts # # Mutators # security.declareProtected(ManagePortal, 'addActionIcon') def addActionIcon(self, category, action_id, icon_expr, title=None, priority=0): """ Add an icon for the given action. o Raise KeyError if an icon has already been defined. """ if self.queryActionInfo(category, action_id) is not None: raise KeyError, 'Duplicate definition!' icons = list(self._icons) icons.append( ActionIcon(category, action_id, icon_expr, title, priority)) self._lookup[(category, action_id)] = icons[-1] self._icons = tuple(icons) security.declareProtected(ManagePortal, 'updateActionIcon') def updateActionIcon(self, category, action_id, icon_expr, title=None, priority=0): """ Update the icon for the given action. o Raise KeyError if an icon has not already been defined. """ if self._lookup.get((category, action_id)) is None: raise KeyError, 'No such definition!' icons = list(self._icons) for ai in icons: if (ai.getCategory() == category and ai.getActionId() == action_id): ai.updateIconExpression(icon_expr) ai._title = title ai._priority = priority break else: raise KeyError, (category, action_id) self._icons = tuple(icons) security.declareProtected(ManagePortal, 'removeActionIcon') def removeActionIcon(self, category, action_id): """ Remove the icon for the given action. o Raise KeyError if an icon has not already been defined. """ if self.queryActionInfo(category, action_id) is None: raise KeyError, 'No such definition (%s, %s)!' % (category, action_id) icons = list(self._icons) icon = self._lookup[(category, action_id)] icons.remove(icon) del self._lookup[(category, action_id)] self._icons = tuple(icons) security.declareProtected(ManagePortal, 'clearActionIcons') def clearActionIcons(self): """ Remove all mappings from the tool. """ self._icons = () self._lookup = {} # # ZMI # manage_options = ({ 'label': 'Icons', 'action': 'manage_editActionIcons' }, ) + SimpleItem.manage_options security.declareProtected(ManagePortal, 'manage_editActionIcons') manage_editActionIcons = PageTemplateResource('www/aitEdit.zpt', globals()) security.declareProtected(ManagePortal, 'manage_addActionIcon') def manage_addActionIcon(self, category, action_id, icon_expr, title, priority, REQUEST): """ Add an icon for the given action via the ZMI. """ self.addActionIcon(category, action_id, icon_expr, title, priority) REQUEST['RESPONSE'].redirect('%s/manage_editActionIcons' '?manage_tabs_message=Action+added.' % self.absolute_url()) security.declareProtected(ManagePortal, 'manage_updateActionIcon') def manage_updateActionIcon(self, category, action_id, icon_expr, title, priority, REQUEST): """ Update an icon for the given action via the ZMI. """ self.updateActionIcon(category, action_id, icon_expr, title, priority) REQUEST['RESPONSE'].redirect('%s/manage_editActionIcons' '?manage_tabs_message=Action+updated.' % self.absolute_url()) security.declareProtected(ManagePortal, 'manage_removeActionIcon') def manage_removeActionIcon(self, category, action_id, REQUEST): """ Remove the icon for the given action via the ZMI. """ self.removeActionIcon(category, action_id) REQUEST['RESPONSE'].redirect('%s/manage_editActionIcons' '?manage_tabs_message=Action+removed.' % self.absolute_url())
class UniqueIdHandlerTool(UniqueObject, SimpleItem, ActionProviderBase): __doc__ = __doc__ # copy from module implements(IUniqueIdHandler, IUniqueIdBrainQuery, IUniqueIdUnrestrictedQuery) __implements__ = ( ActionProviderBase.__implements__, SimpleItem.__implements__, ) id = 'portal_uidhandler' manage_options = ( ActionProviderBase.manage_options + ( {'label':'Query', 'action':'manage_queryObject'} , ) + SimpleItem.manage_options ) alternative_id = "portal_standard_uidhandler" meta_type = 'Unique Id Handler Tool' # make the uid attribute name available for the unit tests # not meant to be altered as long you don't know what you do!!! UID_ATTRIBUTE_NAME = UID_ATTRIBUTE_NAME # make the exception class available through the tool UniqueIdError = UniqueIdError security = ClassSecurityInfo() def _reindexObject(self, obj): # add uid index and colums to catalog if not yet done UID_ATTRIBUTE_NAME = self.UID_ATTRIBUTE_NAME catalog = getToolByName(self, 'portal_catalog') if UID_ATTRIBUTE_NAME not in catalog.indexes(): catalog.addIndex(UID_ATTRIBUTE_NAME, 'FieldIndex') catalog.addColumn(UID_ATTRIBUTE_NAME) # reindex catalog.reindexObject(obj) def _setUid(self, obj, uid): """Attaches a unique id to the object and does reindexing. """ # attach a unique id annotation to the object anno_tool = getToolByName(self, 'portal_uidannotation') annotation = anno_tool(obj, self.UID_ATTRIBUTE_NAME) annotation.setUid(uid) # reindex the object self._reindexObject(obj) security.declarePublic('register') def register(self, obj): """See IUniqueIdSet. """ uid = self.queryUid(obj, default=None) if uid is None: # generate a new unique id and set it generator = getToolByName(self, 'portal_uidgenerator') uid = generator() self._setUid(obj, uid) return uid security.declareProtected(ManagePortal, 'unregister') def unregister(self, obj): """See IUniqueIdSet. """ UID_ATTRIBUTE_NAME = self.UID_ATTRIBUTE_NAME if getattr(aq_base(obj), UID_ATTRIBUTE_NAME, None) is None: raise UniqueIdError, \ "No unique id available to be unregistered on '%s'" % obj # delete the uid and reindex delattr(obj, UID_ATTRIBUTE_NAME) self._reindexObject(obj) security.declarePublic('queryUid') def queryUid(self, obj, default=None): """See IUniqueIdQuery. """ uid = getattr(aq_base(obj), self.UID_ATTRIBUTE_NAME, None) # If 'obj' is a content object the 'uid' attribute is usually a # callable object. If 'obj' is a catalog brain the uid attribute # is non callable and possibly equals the 'Missing.MV' value. if uid is Missing.MV or uid is None: return default if callable(uid): return uid() return uid security.declarePublic('getUid') def getUid(self, obj): """See IUniqueIdQuery. """ uid = self.queryUid(obj, None) if uid is None: raise UniqueIdError, "No unique id available on '%s'" % obj return uid security.declarePrivate('setUid') def setUid(self, obj, uid, check_uniqueness=True): """See IUniqueIdSet. """ # None is the only value a unique id shall never have! if uid is None: raise UniqueIdError, "It's forbidden to set a unique id to 'None'." # check for uniqueness if enabled if check_uniqueness: result = self.queryObject(uid) if result is not None and result != obj: if callable(uid): uid = uid() raise UniqueIdError, \ "The unique id '%s' is already in use" % uid # everything is ok: set it! self._setUid(obj, uid) def _queryBrain(self, uid, searchMethodName, default=None): """This helper method does the "hard work" of querying the catalog and interpreting the results. """ if uid is None: return default # convert the uid to the right format generator = getToolByName(self, 'portal_uidgenerator') uid = generator.convert(uid) catalog = getToolByName(self, 'portal_catalog') searchMethod = getattr(catalog, searchMethodName) result = searchMethod({self.UID_ATTRIBUTE_NAME: uid}) len_result = len(result) # return None if no object found with this uid if len_result == 0: return default # print a message to the log if more than one object has # the same uid (uups!) if len_result > 1: zLOG.LOG("CMUid ASSERT:", zLOG.INFO, "Uups, %s objects have '%s' as uid!!!" % \ (len_result, uid)) return result[0] security.declarePublic('queryBrain') def queryBrain(self, uid, default=None): """See IUniqueIdBrainQuery. """ return self._queryBrain(uid, 'searchResults', default) def _getBrain(self, uid, queryBrainMethod): brain = queryBrainMethod(uid, default=None) if brain is None: raise UniqueIdError, "No object found with '%s' as uid." % uid return brain security.declarePublic('getBrain') def getBrain(self, uid): """See IUniqueIdBrainQuery. """ return self._getBrain(uid, self.queryBrain) security.declarePublic('getObject') def getObject(self, uid): """See IUniqueIdQuery. """ return self.getBrain(uid).getObject() security.declarePublic('queryObject') def queryObject(self, uid, default=None): """See IUniqueIdQuery. """ try: return self.getObject(uid) except UniqueIdError: return default security.declarePrivate('unrestrictedQueryBrain') def unrestrictedQueryBrain(self, uid, default=None): """See IUniqueIdUnrestrictedQuery. """ return self._queryBrain(uid, 'unrestrictedSearchResults', default) security.declarePrivate('unrestrictedGetBrain') def unrestrictedGetBrain(self, uid): """See IUniqueIdUnrestrictedQuery. """ return self._getBrain(uid, self.unrestrictedQueryBrain) security.declarePrivate('unrestrictedGetObject') def unrestrictedGetObject(self, uid): """See IUniqueIdUnrestrictedQuery. """ return self.unrestrictedGetBrain(uid).getObject() security.declarePrivate('unrestrictedQueryObject') def unrestrictedQueryObject(self, uid, default=None): """See IUniqueIdUnrestrictedQuery. """ try: return self.unrestrictedGetObject(uid) except UniqueIdError: return default security.declareProtected(ManagePortal, 'manage_queryObject') manage_queryObject = PageTemplateResource('www/queryUID.pt', globals())
class ExportConfiguratorBase(Implicit): """ Synthesize XML description. """ security = ClassSecurityInfo() security.setDefaultAccess('allow') def __init__(self, site, encoding=None): self._site = site self._encoding = encoding self._template = self._getExportTemplate() security.declareProtected(ManagePortal, 'generateXML') def generateXML(self, **kw): """ Pseudo API. """ return self._template(**kw) # # generic object and property support # _ob_nodes = PageTemplateResource('xml/object_nodes.xml', globals()) _prop_nodes = PageTemplateResource('xml/property_nodes.xml', globals()) security.declareProtected(ManagePortal, 'generateObjectNodes') def generateObjectNodes(self, obj_infos): """ Pseudo API. """ lines = self._ob_nodes(objects=obj_infos).splitlines() return '\n'.join(lines) security.declareProtected(ManagePortal, 'generatePropertyNodes') def generatePropertyNodes(self, prop_infos): """ Pseudo API. """ lines = self._prop_nodes(properties=prop_infos).splitlines() return '\n'.join(lines) def _extractObject(self, obj): properties = [] subobjects = [] i18n_domain = getattr(obj, 'i18n_domain', None) if getattr(aq_base(obj), '_propertyMap'): for prop_map in obj._propertyMap(): prop_info = self._extractProperty(obj, prop_map) if i18n_domain and prop_info['id'] in ('title', 'description'): prop_info['i18ned'] = '' if prop_info['id'] != 'i18n_domain': properties.append(prop_info) if getattr(aq_base(obj), 'objectValues'): for sub in obj.objectValues(): subobjects.append(self._extractObject(sub)) return { 'id': obj.getId(), 'meta_type': obj.meta_type, 'i18n_domain': i18n_domain or None, 'properties': tuple(properties), 'subobjects': tuple(subobjects) } def _extractProperty(self, obj, prop_map): prop_id = prop_map['id'] prop = obj.getProperty(prop_id) if isinstance(prop, tuple): prop_value = '' prop_elements = prop elif isinstance(prop, list): # Backward compat for old instances that stored # properties as list. prop_value = '' prop_elements = tuple(prop) else: prop_value = prop prop_elements = () if 'd' in prop_map.get('mode', 'wd') and not prop_id == 'title': type = prop_map.get('type', 'string') select_variable = prop_map.get('select_variable', None) else: type = None select_variable = None return { 'id': prop_id, 'value': prop_value, 'elements': prop_elements, 'type': type, 'select_variable': select_variable }
class StateDefinition(SimpleItem): """State definition""" meta_type = 'Workflow State' manage_options = ( { 'label': 'Properties', 'action': 'manage_properties' }, { 'label': 'Permissions', 'action': 'manage_permissions' }, { 'label': 'Groups', 'action': 'manage_groups' }, { 'label': 'Variables', 'action': 'manage_variables' }, ) title = '' description = '' transitions = () # The ids of possible transitions. permission_roles = None # { permission: [role] or (role,) } group_roles = None # { group name : (role,) } var_values = None # PersistentMapping if set. Overrides transition exprs. security = ClassSecurityInfo() security.declareObjectProtected(ManagePortal) def __init__(self, id): self.id = id def getId(self): return self.id def getWorkflow(self): return aq_parent(aq_inner(aq_parent(aq_inner(self)))) def getTransitions(self): return filter(self.getWorkflow().transitions.has_key, self.transitions) def getTransitionTitle(self, tid): t = self.getWorkflow().transitions.get(tid, None) if t is not None: return t.title return '' def getAvailableTransitionIds(self): return self.getWorkflow().transitions.keys() def getAvailableVarIds(self): return self.getWorkflow().variables.keys() def getManagedPermissions(self): return list(self.getWorkflow().permissions) def getAvailableRoles(self): return self.getWorkflow().getAvailableRoles() def getPermissionInfo(self, p): """Returns the list of roles to be assigned to a permission. """ roles = None if self.permission_roles: roles = self.permission_roles.get(p, None) if roles is None: return {'acquired': 1, 'roles': []} else: if isinstance(roles, tuple): acq = 0 else: acq = 1 return {'acquired': acq, 'roles': list(roles)} def getGroupInfo(self, group): """Returns the list of roles to be assigned to a group. """ if self.group_roles: return self.group_roles.get(group, ()) return () _properties_form = DTMLResource('dtml/state_properties', globals()) def manage_properties(self, REQUEST, manage_tabs_message=None): """Show state properties ZMI form.""" return self._properties_form( REQUEST, management_view='Properties', manage_tabs_message=manage_tabs_message, ) def setProperties(self, title='', transitions=(), REQUEST=None, description=''): """Set the properties for this State.""" self.title = str(title) self.description = str(description) self.transitions = tuple(map(str, transitions)) if REQUEST is not None: return self.manage_properties(REQUEST, 'Properties changed.') _variables_form = DTMLResource('dtml/state_variables', globals()) def manage_variables(self, REQUEST, manage_tabs_message=None): """Show State variables ZMI form.""" return self._variables_form( REQUEST, management_view='Variables', manage_tabs_message=manage_tabs_message, ) def getVariableValues(self): """Get VariableValues for management UI.""" vv = self.var_values if vv is None: return [] else: return vv.items() def getWorkflowVariables(self): """Get all variables that are available from the workflow and not handled yet. """ wf_vars = self.getAvailableVarIds() if self.var_values is None: return wf_vars ret = [] for vid in wf_vars: if not self.var_values.has_key(vid): ret.append(vid) return ret def addVariable(self, id, value, REQUEST=None): """Add a WorkflowVariable to State.""" if self.var_values is None: self.var_values = PersistentMapping() self.var_values[id] = value if REQUEST is not None: return self.manage_variables(REQUEST, 'Variable added.') def deleteVariables(self, ids=[], REQUEST=None): """Delete a WorkflowVariable from State.""" vv = self.var_values for id in ids: if vv.has_key(id): del vv[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_values is None: self.var_values = PersistentMapping() vv = self.var_values if REQUEST is not None: for id in vv.keys(): fname = 'varval_%s' % id vv[id] = str(REQUEST[fname]) return self.manage_variables(REQUEST, 'Variables changed.') _permissions_form = DTMLResource('dtml/state_permissions', globals()) def manage_permissions(self, REQUEST, manage_tabs_message=None): """Present TTW UI for managing this State's permissions.""" return self._permissions_form( REQUEST, management_view='Permissions', manage_tabs_message=manage_tabs_message, ) def setPermissions(self, REQUEST): """Set the permissions in REQUEST for this State.""" pr = self.permission_roles if pr is None: self.permission_roles = pr = PersistentMapping() pr.clear() for p in self.getManagedPermissions(): roles = [] acquired = REQUEST.get('acquire_' + p, 0) for r in self.getAvailableRoles(): if REQUEST.get('%s|%s' % (p, r), 0): roles.append(r) roles.sort() if not acquired: roles = tuple(roles) pr[p] = roles return self.manage_permissions(REQUEST, 'Permissions changed.') def setPermission(self, permission, acquired, roles): """Set a permission for this State.""" pr = self.permission_roles if pr is None: self.permission_roles = pr = PersistentMapping() if acquired: roles = list(roles) else: roles = tuple(roles) pr[permission] = roles manage_groups = PageTemplateResource('dtml/state_groups.pt', globals()) def setGroups(self, REQUEST, RESPONSE=None): """Set the group to role mappings in REQUEST for this State. """ map = self.group_roles if map is None: self.group_roles = map = PersistentMapping() map.clear() all_roles = self.getWorkflow().getRoles() for group in self.getWorkflow().getGroups(): roles = [] for role in all_roles: if REQUEST.get('%s|%s' % (group, role), 0): roles.append(role) roles.sort() roles = tuple(roles) map[group] = roles if RESPONSE is not None: RESPONSE.redirect( "%s/manage_groups?manage_tabs_message=Groups+changed." % self.absolute_url())