[CMF-checkins] CVS: CMF/CMFCore - ActionsTool.py:1.38.2.1 PortalFolder.py:1.43.18.1 TypesTool.py:1.49.2.1 utils.py:1.36.4.1
Tres Seaver
tseaver@zope.com
Mon, 10 Mar 2003 18:50:26 -0500
Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv2028/CMFCore
Modified Files:
Tag: tseaver-ti_apb_redux-branch
ActionsTool.py PortalFolder.py TypesTool.py utils.py
Log Message:
Landing 'tseaver-typeinfo_as_apb-branch' against current HEAD, using
a new integration branch:
- Merged the branch and fixed up all conflicts; all tests pass.
- Updated all the 'factory_type_information' structures to make the
'action' key a TALES expression (e.g., "document_view" ->
"string:document_view").
Remaining TODOs:
- Write an external method for converting existing type info objects
(they all have dictionaries, instead of ActionInformation objects,
stored in the ZODB). Otherwise, all existing type info objects are
*toast*.
- Perhaps someone can think of a clever way to avoid the need for this
conversion?
=== CMF/CMFCore/ActionsTool.py 1.38 => 1.38.2.1 ===
--- CMF/CMFCore/ActionsTool.py:1.38 Thu Feb 13 02:44:07 2003
+++ CMF/CMFCore/ActionsTool.py Mon Mar 10 18:49:53 2003
@@ -70,6 +70,7 @@
action_providers = ( 'portal_membership'
, 'portal_actions'
, 'portal_registration'
+ , 'portal_types'
, 'portal_discussion'
, 'portal_undo'
, 'portal_syndication'
@@ -176,6 +177,7 @@
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)
@@ -184,27 +186,6 @@
# 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)
=== CMF/CMFCore/PortalFolder.py 1.43 => 1.43.18.1 ===
--- CMF/CMFCore/PortalFolder.py:1.43 Sat Aug 3 23:51:56 2002
+++ CMF/CMFCore/PortalFolder.py Mon Mar 10 18:49:53 2003
@@ -32,38 +32,37 @@
from DynamicType import DynamicType
from utils import getToolByName, _checkPermission
-factory_type_information = ( { 'id' : 'Folder'
- , 'meta_type' : 'Portal Folder'
- , 'description' : """\
-Use folders to put content in categories."""
- , 'icon' : 'folder_icon.gif'
- , 'product' : 'CMFCore'
- , 'factory' : 'manage_addPortalFolder'
- , 'filter_content_types' : 0
- , 'immediate_view' : 'folder_edit_form'
- , 'actions' :
- ( { 'id' : 'view'
- , 'name' : 'View'
- , 'action' : ''
- , 'permissions' : (View,)
- , 'category' : 'folder'
- }
- , { 'id' : 'edit'
- , 'name' : 'Edit'
- , 'action' : 'folder_edit_form'
- , 'permissions' : (ManageProperties,)
- , 'category' : 'folder'
- }
- , { 'id' : 'localroles'
- , 'name' : 'Local Roles'
- , 'action' : 'folder_localrole_form'
- , 'permissions' : (ManageProperties,)
- , 'category' : 'folder'
- }
- )
- }
- ,
- )
+factory_type_information = (
+ { 'id' : 'Folder'
+ , 'meta_type' : 'Portal Folder'
+ , 'description' : """ Use folders to put content in categories."""
+ , 'icon' : 'folder_icon.gif'
+ , 'product' : 'CMFCore'
+ , 'factory' : 'manage_addPortalFolder'
+ , 'filter_content_types' : 0
+ , 'immediate_view' : 'folder_edit_form'
+ , 'actions' : ( { 'id' : 'view'
+ , 'name' : 'View'
+ , 'action' : 'string:'
+ , 'permissions' : (View,)
+ , 'category' : 'folder'
+ }
+ , { 'id' : 'edit'
+ , 'name' : 'Edit'
+ , 'action' : 'string:folder_edit_form'
+ , 'permissions' : (ManageProperties,)
+ , 'category' : 'folder'
+ }
+ , { 'id' : 'localroles'
+ , 'name' : 'Local Roles'
+ , 'action' : 'string:folder_localrole_form'
+ , 'permissions' : (ManageProperties,)
+ , 'category' : 'folder'
+ }
+ )
+ }
+,
+)
class PortalFolder(DynamicType, CMFCatalogAware, Folder):
=== CMF/CMFCore/TypesTool.py 1.49 => 1.49.2.1 ===
--- CMF/CMFCore/TypesTool.py:1.49 Thu Feb 13 02:44:48 2003
+++ CMF/CMFCore/TypesTool.py Mon Mar 10 18:49:53 2003
@@ -14,52 +14,58 @@
$Id$
"""
+import sys
-from Globals import InitializeClass, DTMLFile
-from OFS.Folder import Folder
-
-from utils import _checkPermission
-from utils import _dtmldir
-from utils import cookString
-from utils import SimpleItemWithProperties
-from utils import UniqueObject
-from AccessControl import getSecurityManager, ClassSecurityInfo, Unauthorized
+from Globals import InitializeClass
+from Globals import DTMLFile
+from AccessControl import getSecurityManager
+from AccessControl import ClassSecurityInfo
+from AccessControl import Unauthorized
from Acquisition import aq_base
+from zLOG import LOG, WARNING, ERROR
+
+from OFS.Folder import Folder
import Products
+
+from interfaces.portal_types import ContentTypeInformation as ITypeInformation
+from interfaces.portal_types import portal_types as ITypesTool
+
from ActionProviderBase import ActionProviderBase
from ActionInformation import ActionInformation
from Expression import Expression
-from zLOG import LOG, WARNING, ERROR
-import sys
from CMFCorePermissions import View
from CMFCorePermissions import ManagePortal
from CMFCorePermissions import AccessContentsInformation
-from interfaces.portal_types import ContentTypeInformation as ITypeInformation
-from interfaces.portal_types import portal_types as ITypesTool
+from utils import UniqueObject
+from utils import SimpleItemWithProperties
+from utils import _dtmldir
+from utils import _checkPermission
+from utils import cookString
+from utils import getActionContext
_marker = [] # Create a new marker.
-class TypeInformation (SimpleItemWithProperties):
+class TypeInformation (SimpleItemWithProperties, ActionProviderBase):
"""
Base class for information about a content type.
"""
_isTypeInformation = 1
- manage_options = (SimpleItemWithProperties.manage_options[:1] +
- ({'label':'Actions',
- 'action':'manage_editActionsForm'},) +
- SimpleItemWithProperties.manage_options[1:])
+ manage_options = ( SimpleItemWithProperties.manage_options[:1]
+ + ActionProviderBase.manage_options
+ + SimpleItemWithProperties.manage_options[1:]
+ )
security = ClassSecurityInfo()
+
security.declareProtected(ManagePortal, 'manage_editProperties')
security.declareProtected(ManagePortal, 'manage_changeProperties')
security.declareProtected(ManagePortal, 'manage_propertiesForm')
-
_basic_properties = (
{'id':'title', 'type': 'string', 'mode':'w',
'label':'Title'},
@@ -98,31 +104,50 @@
allowed_content_types = ()
allow_discussion = 0
global_allow = 1
- _actions = ()
def __init__(self, id, **kw):
+
self.id = id
+
+ kw = kw.copy() # Get a modifiable dict.
+
if kw:
- kw = kw.copy() # Get a modifiable dict.
+
if (not kw.has_key('content_meta_type')
and kw.has_key('meta_type')):
kw['content_meta_type'] = kw['meta_type']
+
if (not kw.has_key('content_icon')
and kw.has_key('icon')):
kw['content_icon'] = kw['icon']
+
apply(self.manage_changeProperties, (), kw)
- if kw.has_key('actions'):
- aa = kw['actions']
- actions = []
- for action in aa:
- action = action.copy()
- # Some backward compatibility stuff.
- if not action.has_key('id'):
- action['id'] = cookString(action['name'])
- if not action.has_key('category'):
- action['category'] = 'object'
- actions.append(action)
- self._actions = tuple(actions)
+
+ aa = kw.get( 'actions', () )
+
+ for action in aa:
+
+ action = action.copy()
+
+ # Some backward compatibility stuff.
+ if not action.has_key('id'):
+ action['id'] = cookString(action['name'])
+
+ if not action.has_key('name'):
+ action['name'] = action['id'].capitalize()
+
+ # XXX: historically, action['action'] is simple string
+
+ self.addAction( id=action['id']
+ , name=action['name']
+ , action=action.get( 'action' )
+ , condition=action.get( 'condition' )
+ , permission=action.get('permissions', () )
+ , category=action.get( 'category', 'object' )
+ , visible=action.get( 'visible', 1 )
+ )
+
+
#
# Accessors
@@ -200,14 +225,6 @@
"""
return self.allow_discussion
- security.declarePrivate('getActions')
- def getActions(self):
- """
- Returns the customizable user actions.
- """
- # Private because this returns the actual structure.
- return self._actions
-
security.declarePublic('globalAllow')
def globalAllow(self):
"""
@@ -220,15 +237,15 @@
"""
Return the URL of the action whose ID is id.
"""
- for action in self.getActions():
+ context = getActionContext( self )
+ for action in self.listActions() or ():
- if action.has_key('id'):
- if action['id'] == id:
- return action['action']
+ if action.getId() == id:
+ return action.action( context )
else:
# Temporary backward compatibility.
- if action['name'].lower() == id:
- return action['action']
+ if action.Title().lower() == id:
+ return action.action( context )
if default is _marker:
raise TypeError, ( 'No action "%s" for type "%s"'
@@ -237,181 +254,44 @@
else:
return default
- #
- # Action editing interface
- #
- _actions_form = DTMLFile( 'editActions', _dtmldir )
-
- security.declareProtected(ManagePortal, 'manage_editActionsForm')
- def manage_editActionsForm(self, REQUEST, manage_tabs_message=None):
- """
- Shows the 'Actions' management tab.
- """
- actions = []
- for a in self.getActions():
- a = a.copy()
- p = a['permissions']
- if p:
- a['permission'] = p[0]
- else:
- a['permission'] = ''
- if not a.has_key('category'):
- a['category'] = 'object'
- if not a.has_key('id'):
- a['id'] = cookString(a['name'])
- if not a.has_key( 'visible' ):
- a['visible'] = 1
- actions.append(a)
- # 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)
-
- security.declareProtected(ManagePortal, 'addAction')
- def addAction( self
- , id
- , name
- , action
- , permission
- , category
- , visible=1
- , REQUEST=None
- ):
- """
- Adds an action to the list.
- """
- if not name:
- raise ValueError('A name is required.')
-
- new_actions = self._cloneActions()
-
- new_actions.append( { 'id' : str(id)
- , 'name' : str(name)
- , 'action' : str(action)
- , 'permissions' : (str(permission),)
- , 'category' : str(category)
- , 'visible' : int(visible)
- } )
-
- self._actions = tuple( new_actions )
-
- if REQUEST is not None:
- return self.manage_editActionsForm(
- REQUEST, manage_tabs_message='Added.')
-
- security.declareProtected(ManagePortal, 'changeActions')
- def changeActions(self, properties=None, REQUEST=None):
- """
- Changes the _actions.
- """
- if properties is None:
- properties = REQUEST
- actions = []
- for idx in range(len(self._actions)):
- s_idx = str(idx)
- action = self._actions[idx].copy()
- action.update( {
- 'id': str(properties.get('id_' + s_idx, '')),
- 'name': str(properties.get('name_' + s_idx, '')),
- 'action': str(properties.get('action_' + s_idx, '')),
- 'permissions':
- (properties.get('permission_' + s_idx, ()),),
- 'category': str(properties.get('category_' + s_idx, '')),
- 'visible': not not properties.get('visible_' + s_idx, 0),
- } )
- if not action['name']:
- raise ValueError('A name is required.')
- actions.append( action )
- self._actions = tuple( actions )
- if REQUEST is not None:
- return self.manage_editActionsForm(REQUEST, manage_tabs_message=
- 'Actions changed.')
-
- security.declareProtected(ManagePortal, 'deleteActions')
- def deleteActions(self, selections=(), REQUEST=None):
- """
- Deletes actions.
- """
- sels = list(map(int, selections)) # Convert to a list of integers.
- sels.sort()
- sels.reverse()
-
- new_actions = self._cloneActions()
-
- for idx in sels:
- del new_actions[idx]
-
- self._actions = tuple(new_actions)
-
- if REQUEST is not None:
- return self.manage_editActionsForm(
- REQUEST, manage_tabs_message=(
- 'Deleted %d action(s).' % len(sels)))
-
- security.declareProtected(ManagePortal, 'moveUpActions')
- def moveUpActions(self, selections=(), REQUEST=None):
- """
- Moves the specified actions up one slot.
- """
- sels = list(map(int, selections)) # Convert to a list of integers.
- sels.sort()
-
- new_actions = self._cloneActions()
-
- for idx in sels:
- idx2 = idx - 1
- if idx2 < 0:
- # Wrap to the bottom.
- idx2 = len(new_actions) - 1
- # Swap.
- a = new_actions[idx2]
- new_actions[idx2] = new_actions[idx]
- new_actions[idx] = a
-
- self._actions = tuple(new_actions)
-
- if REQUEST is not None:
- return self.manage_editActionsForm(
- REQUEST, manage_tabs_message=(
- 'Moved up %d action(s).' % len(sels)))
-
- security.declareProtected(ManagePortal, 'moveDownActions')
- def moveDownActions(self, selections=(), REQUEST=None):
- """
- Moves the specified actions down one slot.
- """
- sels = list(map(int, selections)) # Convert to a list of integers.
- sels.sort()
- sels.reverse()
-
- new_actions = self._cloneActions()
-
- for idx in sels:
- idx2 = idx + 1
- if idx2 >= len(new_actions):
- # Wrap to the top.
- idx2 = 0
- # Swap.
- a = new_actions[idx2]
- new_actions[idx2] = new_actions[idx]
- new_actions[idx] = a
-
- self._actions = tuple(new_actions)
-
- if REQUEST is not None:
- return self.manage_editActionsForm(
- REQUEST, manage_tabs_message=(
- 'Moved down %d action(s).' % len(sels)))
-
- security.declarePrivate( '_cloneActions' )
- def _cloneActions( self ):
+ security.declarePrivate( '_convertActions' )
+ def _convertActions( self ):
"""
- Return a "deep copy" of our list of actions.
+ Upgrade dictionary-based actions.
"""
- return map( lambda x: x.copy(), list( self._actions ) )
+ if not self._actions:
+ return
+
+ if type( self._actions[0] ) == type( {} ):
+
+ aa, self._actions = self._actions, ()
+
+ for action in aa:
+
+ # XXX: historically, action['action'] is simple string
+
+ self.addAction( id=action['id']
+ , name=action['name']
+ , action=action.get( 'action' )
+ , condition=action.get( 'condition' )
+ , permission=action.get('permissions', () )
+ , category=action.get( 'category', 'object' )
+ , visible=action.get( 'visible', 1 )
+ )
+ else:
+
+ new_actions = []
+ for clone in self._cloneActions():
+
+ a_expr = clone.getActionExpression()
+
+ # XXX heuristic, may miss
+ if a_expr and ':' not in a_expr and '/' not in a_expr:
+ clone.action = Expression( 'string:%s' % a_expr )
+
+ new_actions.append( clone )
+
+ self._actions = tuple( new_actions )
security.declarePrivate('_finishConstruction')
def _finishConstruction(self, ob):
@@ -617,7 +497,6 @@
id = 'portal_types'
meta_type = 'CMF Types Tool'
- _actions = ()
security = ClassSecurityInfo()
@@ -834,5 +713,21 @@
immediate_url = '%s/%s' % ( ob.absolute_url()
, info.immediate_view )
RESPONSE.redirect( immediate_url )
+
+ security.declarePrivate( 'listActions' )
+ def listActions( self, info=None ):
+ """
+ List type-related actions.
+ """
+ actions = list( self._actions )
+
+ if info is not None:
+
+ type_info = self.getTypeInfo( info.content )
+
+ if type_info is not None:
+ actions.extend( type_info.listActions( info ) )
+
+ return actions
InitializeClass( TypesTool )
=== CMF/CMFCore/utils.py 1.36 => 1.36.4.1 ===
--- CMF/CMFCore/utils.py:1.36 Tue Jan 21 12:53:59 2003
+++ CMF/CMFCore/utils.py Mon Mar 10 18:49:53 2003
@@ -17,6 +17,12 @@
import operator
from types import StringType
+from Globals import package_home
+from Globals import HTMLFile
+from Globals import ImageFile
+from Globals import InitializeClass
+from Globals import MessageDialog
+
from ExtensionClass import Base
from Acquisition import aq_get, aq_inner, aq_parent
@@ -27,12 +33,6 @@
from AccessControl.PermissionRole import rolesForPermissionOn
from AccessControl.Role import gather_permissions
-from Globals import package_home
-from Globals import InitializeClass
-from Globals import HTMLFile
-from Globals import ImageFile
-from Globals import MessageDialog
-
from OFS.PropertyManager import PropertyManager
from OFS.SimpleItem import SimpleItem
from OFS.PropertySheets import PropertySheets
@@ -42,6 +42,8 @@
from OFS.ObjectManager import UNIQUE
except ImportError:
UNIQUE = 2
+from Products.PageTemplates.Expressions import getEngine
+from Products.PageTemplates.Expressions import SecureModuleImporter
security = ModuleSecurityInfo( 'Products.CMFCore.utils' )
@@ -119,7 +121,7 @@
security.declarePrivate('_verifyActionPermissions')
def _verifyActionPermissions(obj, action):
- pp = action.get('permissions', ())
+ pp = action.getPermissions()
if not pp:
return 1
for p in pp:
@@ -127,20 +129,42 @@
return 1
return 0
+security.declarePublic( 'getActionContext' )
+def getActionContext( self ):
+ data = { 'object_url' : ''
+ , 'folder_url' : ''
+ , 'portal_url' : ''
+ , 'object' : None
+ , 'folder' : None
+ , 'portal' : None
+ , 'nothing' : None
+ , 'request' : getattr( self, 'REQUEST', None )
+ , 'modules' : SecureModuleImporter
+ , 'member' : None
+ }
+ return getEngine().getContext( data )
+
security.declarePrivate('_getViewFor')
def _getViewFor(obj, view='view'):
ti = obj.getTypeInfo()
+
if ti is not None:
- actions = ti.getActions()
+
+ context = getActionContext( obj )
+ actions = ti.listActions()
+
for action in actions:
- if action.get('id', None) == view:
- if _verifyActionPermissions(obj, action):
- return obj.restrictedTraverse(action['action'])
+
+ if action.getId() == view:
+ if _verifyActionPermissions( obj, action ):
+ return obj.restrictedTraverse( action.action( context ) )
+
# "view" action is not present or not allowed.
# Find something that's allowed.
for action in actions:
if _verifyActionPermissions(obj, action):
- return obj.restrictedTraverse(action['action'])
+ return obj.restrictedTraverse( action.action( context ) )
+
raise 'Unauthorized', ('No accessible views available for %s' %
'/'.join(obj.getPhysicalPath()))
else:
@@ -364,7 +388,6 @@
tool.icon = 'misc_/%s/%s' % (self.product_name, self.icon)
InitializeClass( ToolInit )
-
addInstanceForm = HTMLFile('dtml/addInstance', globals())