def _extractAction(self, properties, index): """ Extract an ActionInformation from the funky form properties. """ id = str(properties.get('id_%d' % index, '')) title = str(properties.get('name_%d' % index, '')) action = str(properties.get('action_%d' % index, '')) condition = str(properties.get('condition_%d' % index, '')) category = str(properties.get('category_%d' % index, '')) visible = bool(properties.get('visible_%d' % index, False)) permissions = properties.get('permission_%d' % index, ()) if not title: raise ValueError('A title is required.') if category == '': category = 'object' if isinstance(permissions, basestring): permissions = (permissions, ) return ActionInformation(id=id, title=title, action=action, condition=condition, permissions=permissions, category=category, visible=visible)
def addAction(self, id, name, action, condition, permission, category, visible=1, REQUEST=None): """ Adds an action to the list. """ al = self._actions[:] if not name: raise ValueError('A name is required.') if action: a_expr = Expression(text=str(action)) else: a_expr = '' if condition: c_expr = Expression(text=str(condition)) else: c_expr = '' al.append( ActionInformation(id=str(id), title=str(name), action=a_expr, condition=c_expr, permissions=(str(permission), ), category=str(category), visible=int(visible))) self._actions = al if REQUEST is not None: return self.manage_editActionsForm(REQUEST, manage_tabs_message='Added.')
def changeActions(self, properties=None, REQUEST=None): """ Changes the _actions. """ if properties is None: properties = REQUEST actions = self._actions[:] for idx in range(len(actions)): s_idx = str(idx) action = { 'id': str(properties.get('id_' + s_idx, '')), 'name': str(properties.get('name_' + s_idx, '')), 'action': str(properties.get('action_' + s_idx, '')), 'condition': str(properties.get('condition_' + s_idx, '')), 'permissions': (properties.get('permission_' + s_idx, ()), ), 'category': str(properties.get('category_' + s_idx, 'object')), 'visible': properties.get('visible_' + s_idx, 0), } if not action['name']: raise ValueError('A name is required.') # DM: do not override shared element! # a = actions[idx] class Empty: pass a = Empty() a.id = action['id'] a.title = action['name'] if action['action'] is not '': a._action = Expression(text=action['action']) else: a._action = '' if action['condition'] is not '': a.condition = Expression(text=action['condition']) else: a.condition = '' a.permissions = action['permissions'] a.category = action['category'] a.visible = action['visible'] # DM - unshare! severe sharing bug via class variable "_actions" actions[idx] = ActionInformation( id=a.id, title=a.title, action=a._action, condition=a.condition, permissions=a.permissions, category=a.category, visible=a.visible, ) self._actions = actions if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message='Actions changed.')
def _extractAction( self, properties, index ): """ Extract an ActionInformation from the funky form properties. """ id = str( properties.get( 'id_%d' % index, '' ) ) name = str( properties.get( 'name_%d' % index, '' ) ) action = str( properties.get( 'action_%d' % index, '' ) ) condition = str( properties.get( 'condition_%d' % index, '' ) ) category = str( properties.get( 'category_%d' % index, '' )) visible = properties.get( 'visible_%d' % index, 0 ) permissions = properties.get( 'permission_%d' % index, () ) if not name: raise ValueError('A name is required.') if action is not '': action = Expression( text=action ) if condition is not '': condition = Expression( text=condition ) if category == '': category = 'object' if type( visible ) is not type( 0 ): try: visible = int( visible ) except: visible = 0 if type( permissions ) is type( '' ): permissions = ( permissions, ) return ActionInformation( id=id , title=name , action=action , condition=condition , permissions=permissions , category=category , visible=visible )
def addAction( self , id , name , action , condition , permission , category , visible=1 , REQUEST=None ): """ Add an action to our list. """ if not name: raise ValueError('A name is required.') a_expr = action and Expression(text=str(action)) or '' c_expr = condition and Expression(text=str(condition)) or '' if type( permission ) != type( () ): permission = permission and (str(permission),) or () new_actions = self._cloneActions() new_action = ActionInformation( id=str(id) , title=str(name) , action=a_expr , condition=c_expr , permissions=permission , category=str(category) , visible= not not visible ) new_actions.append( new_action ) self._actions = tuple( new_actions ) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message='Added.')
def addAction( self , id , name , action , condition , permission , category , visible=1 , REQUEST=None ): """ Add an action to our list. """ if not name: raise ValueError('A name is required.') action = action and str(action) or '' condition = condition and str(condition) or '' if not isinstance(permission, tuple): permission = (str(permission),) new_actions = self._cloneActions() new_action = ActionInformation( id=str(id) , title=str(name) , category=str(category) , condition=condition , permissions=permission , visible=bool(visible) , action=action ) new_actions.append( new_action ) self._actions = tuple( new_actions ) if REQUEST is not None: return self.manage_editActionsForm( REQUEST, manage_tabs_message='Added.')
def listActions(self, info=None, object=None): """ List all the actions defined by a provider. """ if object is None and info is not None: # BBB (according to the interface) object = info.content if object is None: # The tool itself doesn't provide any action return () actions = [] for mid in globalBrowserMenuService._registry.keys(): menu = getMenu(mid, object, self.REQUEST) for entry in menu: # The action needs a unique name, so we'll build one # from the object_id and the action url. That is sure # to be unique. action = str(entry['action']) if object is None: act_id = 'action_%s' % action else: act_id = 'action_%s_%s' % (object.getId(), action) if entry['filter'] is None: filter = None else: filter = Expression(text=str(entry['filter'])) act = ActionInformation(id=act_id, title=str(entry['title']), action=Expression(text='string:%s' % action), condition=filter, category=str(mid), visible=1) actions.append(act) return tuple(actions)
class UndoTool (UniqueObject, SimpleItem, ActionProviderBase): """ This tool is used to undo changes. """ __implements__ = (IUndoTool, ActionProviderBase.__implements__) id = 'portal_undo' meta_type = 'CMF Undo Tool' _actions = (ActionInformation(id='undo' , title='Undo' , action=Expression( text='string: ${portal_url}/undo_form') , condition=Expression( text='member') , permissions=(ListUndoableChanges,) , category='global' , visible=1 ) , ) security = ClassSecurityInfo() manage_options = ( ActionProviderBase.manage_options + SimpleItem.manage_options + ({ 'label' : 'Overview', 'action' : 'manage_overview' } , )) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile( 'explainUndoTool', _dtmldir ) # # 'portal_undo' interface methods # security.declareProtected(ListUndoableChanges, 'listUndoableTransactionsFor') def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) for t in transactions: # Ensure transaction ids don't have embedded LF. t['id'] = t['id'].replace('\n', '') if not _checkPermission(ManagePortal, portal): # Filter out transactions done by other members of the portal. user_id = _getAuthenticatedUser(self).getId() transactions = filter( lambda record, user_id=user_id: record['user_name'].split()[-1] == user_id, transactions ) return transactions security.declarePublic('undo') def undo(self, object, transaction_info): """ Undo the list of transactions passed in 'transaction_info', first verifying that the current user is allowed to undo them. """ # Belt and suspenders: make sure that the user is actually # allowed to undo the transation(s) in transaction_info. xids = {} # set of allowed transaction IDs allowed = self.listUndoableTransactionsFor( object ) for xid in map( lambda x: x['id'], allowed ): xids[xid] = 1 if type( transaction_info ) == type( '' ): transaction_info = [ transaction_info ] for tinfo in transaction_info: if not xids.get( tinfo, None ): raise Unauthorized object.manage_undo_transactions(transaction_info)
class ActionsTool(UniqueObject, OFS.Folder.Folder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ id = 'portal_actions' _actions = [ActionInformation(id='folderContents' , title='Folder contents' , action=Expression( text='string: ${folder_url}/folder_contents') , condition=Expression( text='python: folder is not object') , permissions=('List folder contents',) , category='object' , visible=1 ) , ActionInformation(id='folderContents' , title='Folder contents' , action=Expression( text='string: ${folder_url}/folder_contents') , condition=Expression( text='python: folder is object') , permissions=('List folder contents',) , category='folder' , visible=1 )] meta_type = 'CMF Actions Tool' action_providers = ('portal_membership' , 'portal_actions' , 'portal_registration' , 'portal_discussion' , 'portal_undo' , 'portal_syndication' , 'portal_workflow' , 'portal_properties') security = ClassSecurityInfo() manage_options = ( ActionProviderBase.manage_options + ({'label' : 'Action Providers', 'action' : 'manage_actionProviders'} , { 'label' : 'Overview', 'action' : 'manage_overview' } , ) + OFS.Folder.Folder.manage_options ) # # ZMI methods # security.declareProtected( CMFCorePermissions.ManagePortal , 'manage_overview' ) manage_overview = DTMLFile( 'explainActionsTool', _dtmldir ) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) # # Programmatically manipulate the list of action providers # security.declarePrivate('listActions') def listActions(self, info=None): """ Lists actions available through the tool. """ return self._actions security.declareProtected( CMFCorePermissions.ManagePortal , 'listActionProviders' ) def listActionProviders(self): """ returns a sequence of action providers known by this tool """ return self.action_providers security.declareProtected(CMFCorePermissions.ManagePortal , 'manage_aproviders') def manage_aproviders(self , apname='' , chosen=() , add_provider=0 , del_provider=0 , REQUEST=None): """ Manage TTW Action Providers """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = providers if REQUEST is not None: return self.manage_actionProviders(self , REQUEST , manage_tabs_message='Properties changed.') security.declareProtected( CMFCorePermissions.ManagePortal , 'addActionProvider' ) def addActionProvider( self, provider_name ): """ add the name of a new action provider """ if hasattr( self, provider_name ): p_old = self.action_providers p_new = p_old + ( provider_name, ) self.action_providers = p_new security.declareProtected( CMFCorePermissions.ManagePortal , 'deleteActionProvider' ) def deleteActionProvider( self, provider_name ): """ remove an action provider """ if provider_name in self.action_providers: p_old = list( self.action_providers ) del p_old[p_old.index( provider_name)] self.action_providers = tuple( p_old ) # # 'portal_actions' interface methods # def _listActions(self,append,object,info,ec): a = object.listActions(info) if a and type(a[0]) is not type({}): for ai in a: if ai.testCondition(ec): append(ai.getAction(ec)) else: for i in a: append(i) security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) ec = createExprContext(folder, portal, object) actions = [] append = actions.append info = oai(self, folder, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) self._listActions(append,provider,info,ec) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName( self, 'portal_types' ) ti = types_tool.getTypeInfo( object ) if ti is not None: defs = ti.getActions() if defs: c_url = object.absolute_url() for d in defs: a = d['action'] if a: url = c_url + '/' + a else: url = c_url actions.append({ 'id': d.get('id', None), 'name': d['name'], 'action': d['action'], 'url': url, 'permissions': d['permissions'], 'category': d.get('category', 'object'), 'visible': d.get('visible', 1), }) if hasattr(base, 'listActions'): self._listActions(append,object,info,ec) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if category in ('object', 'workflow') and object is not None: context = object elif category == 'folder' and folder is not None: context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # Filter out duplicate actions by identity... if not action in catlist: catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the two lines above) #if not [a for a in catlist if a==action]: # catlist.append(action) return filtered_actions # listFilteredActions() is an alias. security.declarePublic('listFilteredActions') listFilteredActions = listFilteredActionsFor
class ActionsTool(UniqueObject, Folder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ __implements__ = (IActionsTool, ActionProviderBase.__implements__) id = 'portal_actions' meta_type = 'CMF Actions Tool' _actions = (ActionInformation(id='folderContents' , title='Folder contents' , action=Expression( text='string:${folder_url}/folder_contents') , condition=Expression( text='python: folder is not object') , permissions=(ListFolderContents,) , category='folder' , visible=1 ) , ) action_providers = ( 'portal_membership' , 'portal_actions' , 'portal_registration' , 'portal_types' , 'portal_discussion' , 'portal_undo' , 'portal_syndication' , 'portal_workflow' , 'portal_properties' ) security = ClassSecurityInfo() manage_options = ( ActionProviderBase.manage_options + ( { 'label' : 'Action Providers' , 'action' : 'manage_actionProviders' } , { 'label' : 'Overview' , 'action' : 'manage_overview' } ) + Folder.manage_options ) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile( 'explainActionsTool', _dtmldir ) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) security.declareProtected(ManagePortal, 'manage_aproviders') def manage_aproviders(self , apname='' , chosen=() , add_provider=0 , del_provider=0 , REQUEST=None): """ Manage action providers through-the-web. """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = tuple(providers) if REQUEST is not None: return self.manage_actionProviders(self , REQUEST , manage_tabs_message='Providers changed.') # # Programmatically manipulate the list of action providers # security.declareProtected(ManagePortal, 'listActionProviders') def listActionProviders(self): """ List the ids of all Action Providers queried by this tool. """ return self.action_providers security.declareProtected(ManagePortal, 'addActionProvider') def addActionProvider( self, provider_name ): """ Add an Action Provider id to the providers queried by this tool. """ ap = list( self.action_providers ) if hasattr( self, provider_name ) and provider_name not in ap: ap.append( provider_name ) self.action_providers = tuple( ap ) security.declareProtected(ManagePortal, 'deleteActionProvider') def deleteActionProvider( self, provider_name ): """ Delete an Action Provider id from providers queried by this tool. """ ap = list( self.action_providers ) if provider_name in ap: ap.remove( provider_name ) self.action_providers = tuple( ap ) # # 'portal_actions' interface methods # security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): """ List all actions available to the user. """ actions = [] # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if IActionProvider.isImplementedBy(provider): actions.extend( provider.listActionInfos(object=object) ) else: # for Action Providers written for CMF versions before 1.5 actions.extend( self._listActionInfos(provider, object) ) # Include actions from object. if object is not None: base = aq_base(object) if IActionProvider.isImplementedBy(base): actions.extend( object.listActionInfos(object=object) ) elif hasattr(base, 'listActions'): # for objects written for CMF versions before 1.5 actions.extend( self._listActionInfos(object, object) ) # Reorganize the actions by category. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: catlist = filtered_actions.setdefault(action['category'], []) catlist.append(action) return filtered_actions # listFilteredActions() is an alias. security.declarePublic('listFilteredActions') listFilteredActions = listFilteredActionsFor # # Helper method for backwards compatibility # def _listActionInfos(self, provider, object): """ for Action Providers written for CMF versions before 1.5 """ warn('ActionProvider interface not up to date. In CMF 2.0 ' 'portal_actions will ignore listActions() of \'%s\'.' % provider.getId(), DeprecationWarning) info = self._getOAI(object) actions = provider.listActions(info) action_infos = [] if actions and not isinstance(actions[0], dict): ec = self._getExprContext(object) for ai in actions: if not ai.getVisibility(): continue permissions = ai.getPermissions() if permissions: category = ai.getCategory() if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue if not ai.testCondition(ec): continue action_infos.append( ai.getAction(ec) ) else: for i in actions: if not i.get('visible', 1): continue permissions = i.get('permissions', None) if permissions: category = i['category'] if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue action_infos.append(i) return action_infos
class ActionsTool(UniqueObject, Folder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ id = 'portal_actions' _actions = [ ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string: ${folder_url}/folder_contents'), condition=Expression(text='python: folder is not object'), permissions=('List folder contents', ), category='object', visible=1), ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string: ${folder_url}/folder_contents'), condition=Expression(text='python: folder is object'), permissions=('List folder contents', ), category='folder', visible=1) ] meta_type = 'CMF Actions Tool' action_providers = ('portal_membership', 'portal_actions', 'portal_registration', 'portal_discussion', 'portal_undo', 'portal_syndication', 'portal_workflow', 'portal_properties') security = ClassSecurityInfo() manage_options = (ActionProviderBase.manage_options + ({ 'label': 'Action Providers', 'action': 'manage_actionProviders' }, { 'label': 'Overview', 'action': 'manage_overview' }) + Folder.manage_options) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainActionsTool', _dtmldir) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) security.declareProtected(ManagePortal, 'manage_aproviders') def manage_aproviders(self, apname='', chosen=(), add_provider=0, del_provider=0, REQUEST=None): """ Manage action providers through-the-web. """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = tuple(providers) if REQUEST is not None: return self.manage_actionProviders( self, REQUEST, manage_tabs_message='Properties changed.') # # ActionProvider interface # security.declarePrivate('listActions') def listActions(self, info=None): """ Return a list of actions available through the tool. """ return self._actions # # Programmatically manipulate the list of action providers # security.declareProtected(ManagePortal, 'listActionProviders') def listActionProviders(self): """ Return a sequence of names of action providers known by this tool. """ return self.action_providers security.declareProtected(ManagePortal, 'addActionProvider') def addActionProvider(self, provider_name): """ Add the name of a new action provider. """ ap = list(self.action_providers)[:] if hasattr(self, provider_name) and provider_name not in ap: ap.append(provider_name) self.action_providers = tuple(ap) security.declareProtected(ManagePortal, 'deleteActionProvider') def deleteActionProvider(self, provider_name): """ Remove an action provider. """ if provider_name in self.action_providers: ap = list(self.action_providers) ap.remove(provider_name) self.action_providers = tuple(ap) # # 'portal_actions' interface methods # security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): '''Gets all actions available to the user and returns a mapping containing user actions, object actions, and global actions. ''' portal = aq_parent(aq_inner(self)) if object is None or not hasattr(object, 'aq_base'): folder = portal else: folder = object # Search up the containment hierarchy until we find an # object that claims it's a folder. while folder is not None: if getattr(aq_base(folder), 'isPrincipiaFolderish', 0): # found it. break else: folder = aq_parent(aq_inner(folder)) ec = createExprContext(folder, portal, object) actions = [] append = actions.append info = oai(self, folder, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) self._listActions(append, provider, info, ec) # Include actions from object. if object is not None: base = aq_base(object) types_tool = getToolByName(self, 'portal_types') # we might get None back from getTypeInfo. We construct # a dummy TypeInformation object here in that case (the 'or' # case). This prevents us from needing to check the condition. ti = types_tool.getTypeInfo(object) or TypeInformation('Dummy') defs = ti.getActions() url = object_url = object.absolute_url() for d in defs: # we can't modify or expose the original actionsd... this # stems from the fact that getActions returns a ref to the # actual dictionary used to store actions instead of a # copy. We copy it here to prevent it from being modified. d = d.copy() d['id'] = d.get('id', None) if d['action']: url = '%s/%s' % (object_url, d['action']) d['url'] = url d['category'] = d.get('category', 'object') d['visible'] = d.get('visible', 1) actions.append(d) if hasattr(base, 'listActions'): self._listActions(append, object, info, ec) # Reorganize the actions by category, # filtering out disallowed actions. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: category = action['category'] permissions = action.get('permissions', None) visible = action.get('visible', 1) if not visible: continue verified = 0 if not permissions: # This action requires no extra permissions. verified = 1 else: if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (folder is not None and category.startswith('folder')): context = folder else: context = portal for permission in permissions: # The user must be able to match at least one of # the listed permissions. if _checkPermission(permission, context): verified = 1 break if verified: catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] # Filter out duplicate actions by identity... if not action in catlist: catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the two lines above) #if not [a for a in catlist if a==action]: # catlist.append(action) return filtered_actions # listFilteredActions() is an alias. security.declarePublic('listFilteredActions') listFilteredActions = listFilteredActionsFor # # Helper methods # security.declarePrivate('_listActions') def _listActions(self, append, object, info, ec): a = object.listActions(info) if a and type(a[0]) is not type({}): for ai in a: if ai.testCondition(ec): append(ai.getAction(ec)) else: for i in a: append(i)
class UndoTool(UniqueObject, SimpleItem, ActionProviderBase): id = 'portal_undo' meta_type = 'CMF Undo Tool' # This tool is used to undo changes. _actions = [ ActionInformation( id='undo', title='Undo', action=Expression(text='string: ${portal_url}/undo_form'), condition=Expression(text='member'), permissions=(ListUndoableChanges, ), category='global', visible=1) ] security = ClassSecurityInfo() manage_options = (ActionProviderBase.manage_options + SimpleItem.manage_options + ({ 'label': 'Overview', 'action': 'manage_overview' }, )) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainUndoTool', _dtmldir) security.declarePrivate('listActions') def listActions(self, info=None): """ List actions available through tool """ return self._actions # # 'portal_undo' interface methods # security.declareProtected(ListUndoableChanges, 'listUndoableTransactionsFor') def listUndoableTransactionsFor(self, object, first_transaction=None, last_transaction=None, PrincipiaUndoBatchSize=None): '''Lists all transaction IDs the user is allowed to undo. ''' # arg list for undoable_transactions() changed in Zope 2.2. portal = self.aq_inner.aq_parent transactions = portal.undoable_transactions( first_transaction=first_transaction, last_transaction=last_transaction, PrincipiaUndoBatchSize=PrincipiaUndoBatchSize) if not _checkPermission('Manage portal', portal): # Filter out transactions done by other members of the portal. user_name = _getAuthenticatedUser(self).getUserName() transactions = filter(lambda record, user_name=user_name: split( record['user_name'])[-1] == user_name, transactions) return transactions security.declareProtected(UndoChanges, 'undo') def undo(self, object, transaction_info): '''Performs an undo operation. ''' object.manage_undo_transactions(transaction_info)
class ActionsTool(UniqueObject, IFAwareObjectManager, OrderedFolder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ __implements__ = (IActionsTool, OrderedFolder.__implements__, ActionProviderBase.__implements__) id = 'portal_actions' meta_type = 'CMF Actions Tool' _product_interfaces = (IActionCategory, ) _actions = (ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string:${folder_url}/folder_contents'), condition=Expression(text='python: folder is not object'), permissions=(ListFolderContents, ), category='folder', visible=1), ) action_providers = ('portal_membership', 'portal_actions', 'portal_registration', 'portal_types', 'portal_discussion', 'portal_undo', 'portal_syndication', 'portal_workflow', 'portal_properties') security = ClassSecurityInfo() manage_options = ((OrderedFolder.manage_options[0], ActionProviderBase.manage_options[0], { 'label': 'Action Providers', 'action': 'manage_actionProviders' }, { 'label': 'Overview', 'action': 'manage_overview' }) + OrderedFolder.manage_options[2:]) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainActionsTool', _dtmldir) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) security.declareProtected(ManagePortal, 'manage_aproviders') def manage_aproviders(self, apname='', chosen=(), add_provider=0, del_provider=0, REQUEST=None): """ Manage action providers through-the-web. """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = tuple(providers) if REQUEST is not None: return self.manage_actionProviders( self, REQUEST, manage_tabs_message='Providers changed.') security.declareProtected(ManagePortal, 'manage_editActionsForm') def manage_editActionsForm(self, REQUEST, manage_tabs_message=None): """ Show the 'Actions' management tab. """ actions = [ai.getMapping() for ai in self._actions] # possible_permissions is in AccessControl.Role.RoleManager. pp = self.possible_permissions() return self._actions_form(self, REQUEST, actions=actions, possible_permissions=pp, management_view='Actions', manage_tabs_message=manage_tabs_message) # # ActionProvider interface # security.declarePrivate('listActions') def listActions(self, info=None, object=None): """ List all the actions defined by a provider. """ actions = list(self._actions) for category in self.objectValues(): actions.extend(category.listActions()) return tuple(actions) # # Programmatically manipulate the list of action providers # security.declareProtected(ManagePortal, 'listActionProviders') def listActionProviders(self): """ List the ids of all Action Providers queried by this tool. """ return self.action_providers security.declareProtected(ManagePortal, 'addActionProvider') def addActionProvider(self, provider_name): """ Add an Action Provider id to the providers queried by this tool. """ ap = list(self.action_providers) if hasattr(self, provider_name) and provider_name not in ap: ap.append(provider_name) self.action_providers = tuple(ap) security.declareProtected(ManagePortal, 'deleteActionProvider') def deleteActionProvider(self, provider_name): """ Delete an Action Provider id from providers queried by this tool. """ ap = list(self.action_providers) if provider_name in ap: ap.remove(provider_name) self.action_providers = tuple(ap) # # 'portal_actions' interface methods # security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): """ List all actions available to the user. """ actions = [] # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if IActionProvider.isImplementedBy(provider): actions.extend(provider.listActionInfos(object=object)) # Include actions from object. if object is not None: if IActionProvider.isImplementedBy(object): actions.extend(object.listActionInfos(object=object)) # Reorganize the actions by category. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: catlist = filtered_actions.setdefault(action['category'], []) catlist.append(action) return filtered_actions
class ActionsTool(UniqueObject, Folder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ __implements__ = (IActionsTool, ActionProviderBase.__implements__) id = 'portal_actions' meta_type = 'CMF Actions Tool' _actions = (ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string:${folder_url}/folder_contents'), condition=Expression(text='python: folder is not object'), permissions=(ListFolderContents, ), category='folder', visible=1), ) action_providers = ('portal_membership', 'portal_actions', 'portal_registration', 'portal_types', 'portal_discussion', 'portal_undo', 'portal_syndication', 'portal_workflow', 'portal_properties') security = ClassSecurityInfo() manage_options = (ActionProviderBase.manage_options + ({ 'label': 'Action Providers', 'action': 'manage_actionProviders' }, { 'label': 'Overview', 'action': 'manage_overview' }) + Folder.manage_options) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainActionsTool', _dtmldir) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) security.declareProtected(ManagePortal, 'manage_aproviders') def manage_aproviders(self, apname='', chosen=(), add_provider=0, del_provider=0, REQUEST=None): """ Manage action providers through-the-web. """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = tuple(providers) if REQUEST is not None: return self.manage_actionProviders( self, REQUEST, manage_tabs_message='Providers changed.') # # Programmatically manipulate the list of action providers # security.declareProtected(ManagePortal, 'listActionProviders') def listActionProviders(self): """ List the ids of all Action Providers queried by this tool. """ return self.action_providers security.declareProtected(ManagePortal, 'addActionProvider') def addActionProvider(self, provider_name): """ Add an Action Provider id to the providers queried by this tool. """ ap = list(self.action_providers) if hasattr(self, provider_name) and provider_name not in ap: ap.append(provider_name) self.action_providers = tuple(ap) security.declareProtected(ManagePortal, 'deleteActionProvider') def deleteActionProvider(self, provider_name): """ Delete an Action Provider id from providers queried by this tool. """ ap = list(self.action_providers) if provider_name in ap: ap.remove(provider_name) self.action_providers = tuple(ap) # # 'portal_actions' interface methods # security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): """ List all actions available to the user. """ #cache = None #cache_mgr = getToolByName(self, 'portal_actionscache', None) #if cache_mgr is not None: # cache = cache_mgr.ZCacheManager_getCache() #if cache is not None: # pm = getToolByName(self, 'portal_membership') # if object is None: # object_url = '' # else: # object_url = object.absolute_url() # if pm.isAnonymousUser(): # member = None # else: # member = pm.getAuthenticatedMember() # # Prepare a cache key. # keyset = {'object_url': object_url, # 'member': member, # } # result = cache.ZCache_get(ob=self, keywords=keyset) # if result is not None: # # Got a cached value. # return result actions = [] ec = getExprContext(self, object) # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if IActionProvider.isImplementedBy(provider): start = time() actions.extend(provider.listActionInfos(object=object, ec=ec)) stop = time() open('/tmp/provider_times', 'a').write('%-20s: %8.3f\n' % (provider_name, (stop - start) * 1000)) else: # for Action Providers written for CMF versions before 1.5 actions.extend(self._listActionInfos(provider, object)) # Include actions from object. if object is not None: base = aq_base(object) if IActionProvider.isImplementedBy(base): actions.extend(object.listActionInfos(object=object)) elif hasattr(base, 'listActions'): # for objects written for CMF versions before 1.5 actions.extend(self._listActionInfos(object, object)) # Reorganize the actions by category. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: catlist = filtered_actions.setdefault(action['category'], []) catlist.append(action) #if cache is not None: # result = cache.ZCache_set(ob=self, data=filtered_actions, # keywords=keyset) return filtered_actions # listFilteredActions() is an alias. security.declarePublic('listFilteredActions') listFilteredActions = listFilteredActionsFor security.declarePrivate('ZCacheable_getModTime') def ZCacheable_getModTime(self, mtime_func=None): '''Returns the highest of the last mod times.''' # Based on: # mtime_func # self.mtime # self.__class__.mtime # (if in a ZClass) zclass_instance.mtime # zclass_instance.__class__.mtime mtime = mtime_func and mtime_func() or 0 base = aq_base(self) return max(getattr(base, '_p_mtime', mtime), mtime) # # Helper method for backwards compatibility # def _listActionInfos(self, provider, object): """ for Action Providers written for CMF versions before 1.5 """ warn( 'ActionProvider interface not up to date. In CMF 1.6 ' 'portal_actions will ignore listActions() of \'%s\'.' % provider.getId(), DeprecationWarning) info = getOAI(self, object) actions = provider.listActions(info) action_infos = [] if actions and not isinstance(actions[0], dict): ec = getExprContext(self, object) for ai in actions: if not ai.getVisibility(): continue permissions = ai.getPermissions() if permissions: category = ai.getCategory() if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue if not ai.testCondition(ec): continue action_infos.append(ai.getAction(ec)) else: for i in actions: if not i.get('visible', 1): continue permissions = i.get('permissions', None) if permissions: category = i['category'] if (object is not None and (category.startswith('object') or category.startswith('workflow'))): context = object elif (info['folder'] is not None and category.startswith('folder')): context = info['folder'] else: context = info['portal'] for permission in permissions: allowed = _checkPermission(permission, context) if allowed: break if not allowed: continue action_infos.append(i) return action_infos
class ActionsTool(UniqueObject, Folder, ActionProviderBase): """ Weave together the various sources of "actions" which are apropos to the current user and context. """ __implements__ = (IActionsTool, ActionProviderBase.__implements__) id = 'portal_actions' meta_type = 'CMF Actions Tool' _actions = (ActionInformation( id='folderContents', title='Folder contents', action=Expression(text='string:${folder_url}/folder_contents'), condition=Expression(text='python: folder is not object'), permissions=(ListFolderContents, ), category='folder', visible=1), ) action_providers = ('portal_membership', 'portal_actions', 'portal_registration', 'portal_types', 'portal_discussion', 'portal_undo', 'portal_syndication', 'portal_workflow', 'portal_properties') security = ClassSecurityInfo() manage_options = (ActionProviderBase.manage_options + ({ 'label': 'Action Providers', 'action': 'manage_actionProviders' }, { 'label': 'Overview', 'action': 'manage_overview' }) + Folder.manage_options) # # ZMI methods # security.declareProtected(ManagePortal, 'manage_overview') manage_overview = DTMLFile('explainActionsTool', _dtmldir) manage_actionProviders = DTMLFile('manageActionProviders', _dtmldir) security.declareProtected(ManagePortal, 'manage_aproviders') def manage_aproviders(self, apname='', chosen=(), add_provider=0, del_provider=0, REQUEST=None): """ Manage action providers through-the-web. """ providers = list(self.listActionProviders()) new_providers = [] if add_provider: providers.append(apname) elif del_provider: for item in providers: if item not in chosen: new_providers.append(item) providers = new_providers self.action_providers = tuple(providers) if REQUEST is not None: return self.manage_actionProviders( self, REQUEST, manage_tabs_message='Providers changed.') # # Programmatically manipulate the list of action providers # security.declareProtected(ManagePortal, 'listActionProviders') def listActionProviders(self): """ List the ids of all Action Providers queried by this tool. """ return self.action_providers security.declareProtected(ManagePortal, 'addActionProvider') def addActionProvider(self, provider_name): """ Add an Action Provider id to the providers queried by this tool. """ ap = list(self.action_providers) if hasattr(self, provider_name) and provider_name not in ap: ap.append(provider_name) self.action_providers = tuple(ap) security.declareProtected(ManagePortal, 'deleteActionProvider') def deleteActionProvider(self, provider_name): """ Delete an Action Provider id from providers queried by this tool. """ ap = list(self.action_providers) if provider_name in ap: ap.remove(provider_name) self.action_providers = tuple(ap) # # 'portal_actions' interface methods # security.declarePublic('listFilteredActionsFor') def listFilteredActionsFor(self, object=None): """ List all actions available to the user. """ actions = [] # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if IActionProvider.isImplementedBy(provider): actions.extend(provider.listActionInfos(object=object)) # Include actions from object. if object is not None: if IActionProvider.isImplementedBy(object): actions.extend(object.listActionInfos(object=object)) # Reorganize the actions by category. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: category = action['category'] catlist = filtered_actions.get(category, None) if catlist is None: filtered_actions[category] = catlist = [] catlist.append(action) # ...should you need it, here's some code that filters # by equality (use instead of the line above) #if not action in catlist: # catlist.append(action) return filtered_actions # listFilteredActions() is an alias. security.declarePublic('listFilteredActions') listFilteredActions = listFilteredActionsFor