[CMF-checkins] CVS: Products/CMFCore - ActionInformation.py:1.24
ActionProviderBase.py:1.29 ActionsTool.py:1.50
DiscussionTool.py:1.16 WorkflowTool.py:1.45
Yvo Schubbe
y.2004_ at wcm-solutions.de
Mon Jul 26 06:13:44 EDT 2004
Update of /cvs-repository/Products/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv8720/CMFCore
Modified Files:
ActionInformation.py ActionProviderBase.py ActionsTool.py
DiscussionTool.py WorkflowTool.py
Log Message:
- merged yuppie-apb-redo-branch:
o Removed again OldstyleActionProvider Interface and
OldstyleActionProviderBase that existed only in 1.5.0-alpha.
ActionProvider now also works with oldstyle Action mappings.
o listActionInfos() and getActionInfo() now return ActionInfo objects
instead of Action info mappings. ActionInfo objects have a backwards
compatible mapping interface.
(hope there are no issues with this checkin, I'll be AFK the next 4 days)
=== Products/CMFCore/ActionInformation.py 1.23 => 1.24 ===
--- Products/CMFCore/ActionInformation.py:1.23 Mon Jul 19 14:11:35 2004
+++ Products/CMFCore/ActionInformation.py Mon Jul 26 06:13:13 2004
@@ -20,13 +20,97 @@
from Globals import InitializeClass
from OFS.SimpleItem import SimpleItem
+from interfaces.portal_actions import ActionInfo as IActionInfo
from Expression import Expression
from permissions import View
+from utils import _checkPermission
from utils import getToolByName
_unchanged = [] # marker
+class ActionInfo(dict):
+ """ A lazy dictionary for Action infos.
+ """
+ __implements__ = IActionInfo
+ __allow_access_to_unprotected_subobjects__ = 1
+
+ def __init__(self, action, ec):
+ self._marker = marker = object()
+
+ if isinstance(action, dict):
+ dict.__init__(self, action)
+ self.setdefault( 'id', self['name'].lower() )
+ self.setdefault( 'title', self['name'] )
+ self.setdefault( 'url', '' )
+ self.setdefault( 'permissions', () )
+ self.setdefault( 'category', 'object' )
+ self.setdefault( 'visible', True )
+ self['available'] = True
+ self['allowed'] = self['permissions'] and marker or True
+
+ else:
+ self._action = action
+ self._ec = ec
+ mapping = action.getMapping()
+ self['id'] = mapping['id']
+ self['title'] = mapping['title']
+ self['name'] = mapping['title']
+ self['url'] = mapping['action'] and marker or ''
+ self['permissions'] = mapping['permissions']
+ self['category'] = mapping['category']
+ self['visible'] = mapping['visible']
+ self['available'] = mapping['condition'] and marker or True
+ self['allowed'] = mapping['permissions'] and marker or True
+
+ def __getitem__(self, key):
+ value = dict.__getitem__(self, key)
+ if value == self._marker:
+ if key == 'allowed':
+ value = self[key] = self._checkPermissions()
+ elif key == 'available':
+ value = self[key] = self._checkCondition()
+ elif key == 'url':
+ value = self[key] = self._getURL()
+ return value
+
+ def __eq__(self, other):
+ # this is expensive, use it with care
+ [ self[key] for key in self ]
+ [ other[key] for key in other ]
+ return dict.__eq__(self, other)
+
+ def _getURL(self):
+ """ Get the result of the URL expression in the current context.
+ """
+ return self._action._getActionObject()(self._ec)
+
+ def _checkCondition(self):
+ """ Check condition expression in the current context.
+ """
+ return self._action.testCondition(self._ec)
+
+ def _checkPermissions(self):
+ """ Check permissions in the current context.
+ """
+ category = self['category']
+ object = self._ec.contexts['object']
+ if object is not None and ( category.startswith('object') or
+ category.startswith('workflow') ):
+ context = object
+ else:
+ folder = self._ec.contexts['folder']
+ if folder is not None and category.startswith('folder'):
+ context = folder
+ else:
+ context = self._ec.contexts['portal']
+
+ for permission in self['permissions']:
+ if _checkPermission(permission, context):
+ return True
+ return False
+
+
class ActionInformation( SimpleItem ):
""" Represent a single selectable action.
@@ -123,9 +207,9 @@
""" Evaluate condition using context, 'ec', and return 0 or 1.
"""
if self.condition:
- return self.condition(ec)
+ return bool( self.condition(ec) )
else:
- return 1
+ return True
security.declarePublic( 'getAction' )
def getAction( self, ec ):
@@ -133,17 +217,7 @@
""" Compute the action using context, 'ec'; return a mapping of
info about the action.
"""
- info = {}
- info['id'] = self.id
- info['title'] = info['name'] = self.Title()
- expr = self.getActionExpression()
- __traceback_info__ = (info['id'], info['name'], expr)
- action_obj = self._getActionObject()
- info['url'] = action_obj and action_obj( ec ) or ''
- info['permissions'] = self.getPermissions()
- info['category'] = self.getCategory()
- info['visible'] = self.getVisibility()
- return info
+ return ActionInfo(self, ec)
security.declarePrivate( '_getActionObject' )
def _getActionObject( self ):
@@ -168,7 +242,7 @@
action = self._getActionObject()
expr = action and action.text or ''
if expr and isinstance(expr, basestring):
- if not expr.startswith('python:') and not expr.startswith('string:'):
+ if not expr.startswith('string:') and not expr.startswith('python:'):
expr = 'string:${object_url}/%s' % expr
self.action = Expression( expr )
return expr
@@ -176,7 +250,7 @@
security.declarePrivate( 'setActionExpression' )
def setActionExpression(self, action):
if action and isinstance(action, basestring):
- if not action.startswith('python:') and not action.startswith('string:'):
+ if not action.startswith('string:') and not action.startswith('python:'):
action = 'string:${object_url}/%s' % action
action = Expression( action )
self.action = action
@@ -215,13 +289,14 @@
def getMapping(self):
""" Get a mapping of this object's data.
"""
- return { 'id': self.getId(),
- 'title': self.Title(),
- 'description': self.Description(),
- 'category': self.getCategory(),
- 'condition': self.getCondition(),
- 'permissions': self.getPermissions(),
- 'visible': self.getVisibility(),
+ return { 'id': self.id,
+ 'title': self.title or self.id,
+ 'description': self.description,
+ 'category': self.category or 'object',
+ 'condition': getattr(self, 'condition', None)
+ and self.condition.text or '',
+ 'permissions': self.permissions,
+ 'visible': bool(self.visible),
'action': self.getActionExpression() }
security.declarePrivate('clone')
=== Products/CMFCore/ActionProviderBase.py 1.28 => 1.29 ===
--- Products/CMFCore/ActionProviderBase.py:1.28 Mon Jul 19 14:11:35 2004
+++ Products/CMFCore/ActionProviderBase.py Mon Jul 26 06:13:13 2004
@@ -19,15 +19,11 @@
from Globals import DTMLFile
from Globals import InitializeClass
+from ActionInformation import ActionInfo
from ActionInformation import ActionInformation
-from ActionInformation import getOAI
-from Expression import Expression
from Expression import getExprContext
from interfaces.portal_actions import ActionProvider as IActionProvider
-from interfaces.portal_actions \
- import OldstyleActionProvider as IOldstyleActionProvider
from permissions import ManagePortal
-from utils import _checkPermission
from utils import _dtmldir
@@ -80,11 +76,12 @@
def listActionInfos(self, action_chain=None, object=None,
check_visibility=1, check_permissions=1,
check_condition=1, max=-1):
- # List Action info mappings.
+ # List ActionInfo objects.
# (method is without docstring to disable publishing)
#
ec = getExprContext(self, object)
actions = self.listActions(object=object)
+ actions = [ ActionInfo(action, ec) for action in actions ]
if action_chain:
filtered_actions = []
@@ -94,36 +91,19 @@
sep = action_ident.rfind('/')
category, id = action_ident[:sep], action_ident[sep+1:]
for ai in actions:
- if id == ai.getId() and category == ai.getCategory():
+ if id == ai['id'] and category == ai['category']:
filtered_actions.append(ai)
actions = filtered_actions
action_infos = []
for ai in actions:
- if check_visibility and not ai.getVisibility():
+ if check_visibility and not ai['visible']:
+ continue
+ if check_permissions and not ai['allowed']:
continue
- if check_permissions:
- permissions = ai.getPermissions()
- if permissions:
- category = ai.getCategory()
- if (object is not None and
- (category.startswith('object') or
- category.startswith('workflow'))):
- context = object
- elif (ec.contexts['folder'] is not None and
- category.startswith('folder')):
- context = ec.contexts['folder']
- else:
- context = ec.contexts['portal']
- for permission in permissions:
- allowed = _checkPermission(permission, context)
- if allowed:
- break
- if not allowed:
- continue
- if check_condition and not ai.testCondition(ec):
+ if check_condition and not ai['available']:
continue
- action_infos.append( ai.getAction(ec) )
+ action_infos.append(ai)
if max + 1 and len(action_infos) >= max:
break
return action_infos
@@ -131,7 +111,7 @@
security.declarePublic('getActionInfo')
def getActionInfo(self, action_chain, object=None, check_visibility=0,
check_condition=0):
- """ Get an Action info mapping specified by a chain of actions.
+ """ Get an ActionInfo object specified by a chain of actions.
"""
action_infos = self.listActionInfos(action_chain, object,
check_visibility=check_visibility,
@@ -176,8 +156,8 @@
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 ''
+ action = action and str(action) or ''
+ condition = condition and str(condition) or ''
if not isinstance(permission, tuple):
permission = (str(permission),)
@@ -186,11 +166,11 @@
new_action = ActionInformation( id=str(id)
, title=str(name)
- , action=a_expr
- , condition=c_expr
- , permissions=permission
, category=str(category)
- , visible=int(visible)
+ , condition=condition
+ , permissions=permission
+ , visible=bool(visible)
+ , action=action
)
new_actions.append( new_action )
@@ -337,88 +317,3 @@
)
InitializeClass(ActionProviderBase)
-
-
-class OldstyleActionProviderBase:
- """ Base class for ActionProviders with oldstyle Actions.
- """
-
- __implements__ = IOldstyleActionProvider
-
- security = ClassSecurityInfo()
-
- _actions = ()
-
- #
- # OldstyleActionProvider interface
- #
- security.declarePrivate('listActions')
- def listActions(self, info):
- """ List all the actions defined by a provider.
- """
- return self._actions or ()
-
- security.declarePrivate('getActionObject')
- getActionObject = ActionProviderBase.getActionObject.im_func
-
- security.declarePublic('listActionInfos')
- def listActionInfos(self, action_chain=None, object=None,
- check_visibility=1, check_permissions=1,
- check_condition=1, max=-1):
- # List Action info mappings.
- # (method is without docstring to disable publishing)
- #
- info = getOAI(self, object)
- actions = self.listActions(info=info)
-
- if action_chain:
- filtered_actions = []
- if isinstance(action_chain, basestring):
- action_chain = (action_chain,)
- for action_ident in action_chain:
- sep = action_ident.rfind('/')
- category, id = action_ident[:sep], action_ident[sep+1:]
- for ai in actions:
- if id == ai['id'] and category == ai['category']:
- filtered_actions.append(ai)
- actions = filtered_actions
-
- action_infos = []
- for ai in actions:
- if check_permissions:
- permissions = ai.get( 'permissions', () )
- if permissions:
- category = ai['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(ai)
- if max + 1 and len(action_infos) >= max:
- break
- return action_infos
-
- security.declarePublic('getActionInfo')
- def getActionInfo(self, action_chain, object=None, check_visibility=0,
- check_condition=0):
- """ Get an Action info mapping specified by a chain of actions.
- """
- action_infos = self.listActionInfos(action_chain, object,
- check_visibility=check_visibility,
- check_condition=check_condition, max=1)
- if not action_infos:
- raise ValueError('No Action meets the given specification.')
- return action_infos[0]
-
-InitializeClass(OldstyleActionProviderBase)
=== Products/CMFCore/ActionsTool.py 1.49 => 1.50 ===
--- Products/CMFCore/ActionsTool.py:1.49 Tue Jul 13 12:49:39 2004
+++ Products/CMFCore/ActionsTool.py Mon Jul 26 06:13:13 2004
@@ -28,6 +28,7 @@
from ActionProviderBase import ActionProviderBase
from Expression import Expression
from Expression import getExprContext
+from interfaces.portal_actions import ActionProvider as IActionProvider
from interfaces.portal_actions import portal_actions as IActionsTool
from permissions import ListFolderContents
from permissions import ManagePortal
@@ -153,7 +154,7 @@
# Include actions from specific tools.
for provider_name in self.listActionProviders():
provider = getattr(self, provider_name)
- if hasattr( aq_base(provider), 'listActionInfos' ):
+ if IActionProvider.isImplementedBy(provider):
actions.extend( provider.listActionInfos(object=object) )
else:
# for Action Providers written for CMF versions before 1.5
@@ -162,7 +163,7 @@
# Include actions from object.
if object is not None:
base = aq_base(object)
- if hasattr(base, 'listActionInfos'):
+ if IActionProvider.isImplementedBy(base):
actions.extend( object.listActionInfos(object=object) )
elif hasattr(base, 'listActions'):
# for objects written for CMF versions before 1.5
@@ -180,12 +181,10 @@
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)
+ 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]:
+ # by equality (use instead of the line above)
+ #if not action in catlist:
# catlist.append(action)
return filtered_actions
=== Products/CMFCore/DiscussionTool.py 1.15 => 1.16 ===
--- Products/CMFCore/DiscussionTool.py:1.15 Thu Apr 29 12:13:16 2004
+++ Products/CMFCore/DiscussionTool.py Mon Jul 26 06:13:13 2004
@@ -20,7 +20,7 @@
from Acquisition import Implicit
from AccessControl import ClassSecurityInfo
-from ActionProviderBase import OldstyleActionProviderBase
+from ActionProviderBase import ActionProviderBase
from permissions import AccessContentsInformation
from permissions import ManagePortal
from permissions import ReplyToItem
@@ -112,10 +112,10 @@
return ""
-class DiscussionTool (UniqueObject, SimpleItem, OldstyleActionProviderBase):
+class DiscussionTool (UniqueObject, SimpleItem, ActionProviderBase):
__implements__ = (IOldstyleDiscussionTool,
- OldstyleActionProviderBase.__implements__)
+ ActionProviderBase.__implements__)
id = 'portal_discussion'
meta_type = 'Oldstyle CMF Discussion Tool'
@@ -156,11 +156,13 @@
return 0
security.declarePrivate('listActions')
- def listActions(self, info):
+ def listActions(self, info=None, object=None):
# Return actions for reply and show replies
+ if object is not None or info is None:
+ info = getOAI(self, object)
content = info.content
if content is None or not self.isDiscussionAllowedFor(content):
- return []
+ return ()
discussion = self.getDiscussionFor(content)
if discussion.aq_base == content.aq_base:
=== Products/CMFCore/WorkflowTool.py 1.44 => 1.45 ===
--- Products/CMFCore/WorkflowTool.py:1.44 Thu Apr 29 12:13:17 2004
+++ Products/CMFCore/WorkflowTool.py Mon Jul 26 06:13:13 2004
@@ -22,7 +22,8 @@
from AccessControl import ClassSecurityInfo
from Acquisition import aq_base, aq_inner, aq_parent
-from ActionProviderBase import OldstyleActionProviderBase
+from ActionInformation import getOAI
+from ActionProviderBase import ActionProviderBase
from permissions import ManagePortal
from interfaces.portal_workflow import portal_workflow as IWorkflowTool
from utils import _dtmldir
@@ -54,13 +55,13 @@
raise KeyError, name
-class WorkflowTool(UniqueObject, Folder, OldstyleActionProviderBase):
+class WorkflowTool(UniqueObject, Folder, ActionProviderBase):
""" Mediator tool, mapping workflow objects
"""
id = 'portal_workflow'
meta_type = 'CMF Workflow Tool'
__implements__ = (IWorkflowTool,
- OldstyleActionProviderBase.__implements__)
+ ActionProviderBase.__implements__)
_chains_by_type = None # PersistentMapping
_default_chain = ('default_workflow',)
@@ -230,7 +231,7 @@
return vars
security.declarePrivate('listActions')
- def listActions(self, info):
+ def listActions(self, info=None, object=None):
""" Returns a list of actions to be displayed to the user.
@@ -243,9 +244,12 @@
o Global actions are supplied by all workflows.
"""
+ if object is not None or info is None:
+ info = getOAI(self, object)
chain = self.getChainFor(info.content)
did = {}
actions = []
+
for wf_id in chain:
did[wf_id] = 1
wf = self.getWorkflowById(wf_id)
More information about the CMF-checkins
mailing list