[CMF-checkins] CVS: CMF/CMFCore - ActionsTool.py:1.27.8.1 TypesTool.py:1.37.2.1 utils.py:1.23.2.1
Tres Seaver
tseaver@zope.com
Sat, 6 Jul 2002 18:55:34 -0400
Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv14302/CMFCore
Modified Files:
Tag: tseaver-typeinfo_as_apb-branch
ActionsTool.py TypesTool.py utils.py
Log Message:
- Check in initial pass at basing TypeInformation on ActionProviderBase
(and therefore removing old, stale implementation of type actions).
=== CMF/CMFCore/ActionsTool.py 1.27 => 1.27.8.1 ===
append = actions.append
info = oai(self, folder, object)
+
# Include actions from specific tools.
for provider_name in self.listActionProviders():
provider = getattr(self, provider_name)
@@ -199,27 +200,6 @@
# 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)
=== CMF/CMFCore/TypesTool.py 1.37 => 1.37.2.1 ===
#
##############################################################################
+""" Type registration tool.
+$Id$
"""
- Type registration tool.
- $Id$
-"""
-__version__='$Revision$'[11:-2]
-
-import OFS
from Globals import InitializeClass, DTMLFile
-from utils import UniqueObject, SimpleItemWithProperties, tuplize
-from utils import _dtmldir, _checkPermission, cookString, getToolByName
-import string
-from AccessControl import getSecurityManager, ClassSecurityInfo, Unauthorized
+from AccessControl import getSecurityManager
+from AccessControl import ClassSecurityInfo
+from AccessControl import Unauthorized
from Acquisition import aq_base
-import Products, CMFCorePermissions
+from zLOG import LOG, WARNING
+
+from OFS.Folder import Folder
+import Products
+
+
from ActionProviderBase import ActionProviderBase
from ActionInformation import ActionInformation
from Expression import Expression
-from zLOG import LOG, WARNING
-
-from CMFCorePermissions import View, ManagePortal, AccessContentsInformation
+from CMFCorePermissions import View
+from CMFCorePermissions import ManagePortal
+from CMFCorePermissions import AccessContentsInformation
+from utils import UniqueObject
+from utils import SimpleItemWithProperties
+from utils import tuplize
+from utils import _dtmldir
+from utils import _checkPermission
+from utils import cookString
+from utils import getToolByName
+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(CMFCorePermissions.ManagePortal,
+ security.declareProtected(ManagePortal,
'manage_editProperties',
'manage_changeProperties',
'manage_propertiesForm',
@@ -92,31 +100,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
@@ -194,14 +221,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):
"""
@@ -214,15 +233,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 string.lower(action['name']) == 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"'
@@ -231,180 +250,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 = {
- '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 )
InitializeClass( TypeInformation )
@@ -575,17 +458,16 @@
]
-class TypesTool( UniqueObject, OFS.Folder.Folder, ActionProviderBase ):
+class TypesTool( UniqueObject, Folder, ActionProviderBase ):
"""
Provides a configurable registry of portal content types.
"""
id = 'portal_types'
meta_type = 'CMF Types Tool'
- _actions = []
security = ClassSecurityInfo()
- manage_options = ( OFS.Folder.Folder.manage_options +
+ manage_options = ( Folder.manage_options +
ActionProviderBase.manage_options +
({ 'label' : 'Overview', 'action' : 'manage_overview' }
,
@@ -594,18 +476,10 @@
#
# ZMI methods
#
- security.declareProtected( CMFCorePermissions.ManagePortal
+ security.declareProtected( ManagePortal
, 'manage_overview' )
manage_overview = DTMLFile( 'explainTypesTool', _dtmldir )
- security.declarePrivate('listActions')
- def listActions(self, info=None):
- """
- Return a list of action information instances
- for actions provided via tool
- """
- return self._actions
-
def all_meta_types(self):
"""Adds TypesTool-specific meta types."""
all = TypesTool.inheritedAttribute('all_meta_types')(self)
@@ -809,5 +683,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.23 => 1.23.2.1 ===
##############################################################################
+import os
+import re
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 AccessControl import ClassSecurityInfo, getSecurityManager
+from Acquisition import aq_get, aq_inner, aq_parent
+
+from AccessControl import ClassSecurityInfo
+from AccessControl import getSecurityManager
from AccessControl.Permission import Permission
from AccessControl.PermissionRole import rolesForPermissionOn
from AccessControl.Role import gather_permissions
-import Globals
-from Acquisition import aq_get, aq_inner, aq_parent
-from string import split
-import os, re
-from Globals import package_home
-from string import lower
-try: from OFS.ObjectManager import UNIQUE
-except ImportError: UNIQUE = 2
+from Products.PageTemplates.Expressions import getEngine
+from Products.PageTemplates.Expressions import SecureModuleImporter
+
+try:
+ from OFS.ObjectManager import UNIQUE
+except ImportError:
+ UNIQUE = 2
_dtmldir = os.path.join( package_home( globals() ), 'dtml' )
@@ -54,10 +64,10 @@
class ImmutableId (Base):
def _setId(self, id):
if id != self.getId():
- raise Globals.MessageDialog(
- title='Invalid Id',
- message='Cannot change the id of this object',
- action ='./manage_main',)
+ raise MessageDialog( title='Invalid Id'
+ , message='Cannot change the id of this object'
+ , action ='./manage_main'
+ )
class UniqueObject (ImmutableId):
@@ -71,13 +81,13 @@
friendly id.
"""
rgx = re.compile(r'(^_|[^a-zA-Z0-9-_~\,\.])')
- cooked = string.lower(re.sub(rgx, "",text))
+ cooked = re.sub(rgx, "",text).lower()
return cooked
def tuplize( valueName, value ):
if type(value) == type(()): return value
if type(value) == type([]): return tuple( value )
- if type(value) == type(''): return tuple( split( value ) )
+ if type(value) == type(''): return tuple( value.split() )
raise ValueError, "%s of unsupported type" % valueName
def _getAuthenticatedUser( self ):
@@ -91,8 +101,22 @@
return 1
return 0
+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 )
+
def _verifyActionPermissions(obj, action):
- pp = action.get('permissions', ())
+ pp = action.getPermissions()
if not pp:
return 1
for p in pp:
@@ -102,17 +126,24 @@
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' %
string.join(obj.getPhysicalPath(), '/'))
else:
@@ -219,8 +250,6 @@
return something_changed
-from Globals import HTMLFile
-
addInstanceForm = HTMLFile('dtml/addInstance', globals())
@@ -257,7 +286,7 @@
tool.icon = 'misc_/%s/%s' % (self.product_name, self.icon)
-Globals.InitializeClass( ToolInit )
+InitializeClass( ToolInit )
def manage_addToolForm(self, REQUEST):
'''
@@ -337,7 +366,7 @@
for ct in self.content_types:
ct.__factory_meta_type__ = self.meta_type
-Globals.InitializeClass( ContentInit )
+InitializeClass( ContentInit )
def manage_addContentForm(self, REQUEST):
'''
@@ -411,7 +440,7 @@
return id
-Globals.InitializeClass( SimpleItemWithProperties )
+InitializeClass( SimpleItemWithProperties )
import OFS
@@ -448,10 +477,10 @@
def registerIcon(klass, iconspec, _prefix=None):
modname = klass.__module__
- pid = split(modname, '.')[1]
+ pid = modname.split('.')[1]
name = path.split(iconspec)[1]
klass.icon = 'misc_/%s/%s' % (pid, name)
- icon = Globals.ImageFile(iconspec, _prefix)
+ icon = ImageFile(iconspec, _prefix)
icon.__roles__=None
if not hasattr(OFS.misc_.misc_, pid):
setattr(OFS.misc_.misc_, pid, OFS.misc_.Misc_(pid, {}))
@@ -567,75 +596,3 @@
while p[:1] in separators:
p = p[1:]
return p
-
-if 0:
- # Hopefully we can use this.
-
- from Globals import Persistent
-
- class NotifyOnModify (Persistent):
- '''
- This base class allows instances to be notified when there are
- changes that would affect persistence.
- '''
-
- __ready = 0
-
- def _setNotifyModified(self):
- self.__ready = 1
-
- def __doNotify(self):
- if self.__ready:
- dict = self.__dict__
- if not dict.has_key('__notified_on_modify__'):
- dict['__notified_on_modify__'] = 1
- self.notifyModified()
-
- def __setattr__(self, name, val):
- self.__dict__[name] = val
- self._p_changed = 1
- self.__doNotify()
-
- def __delattr__(self, name):
- del self.__dict__[name]
- self._p_changed = 1
- self.__doNotify()
-
- def notifyModified(self):
- # To be overridden.
- pass
-
-
-if 0:
- # Prototype for a "UniqueId" base ZClass.
- import OFS
-
- class UniqueSheet(OFS.PropertySheets.PropertySheet,
- OFS.PropertySheets.View):
- 'Manage id of unique objects'
-
- manage = Globals.HTMLFile('uniqueid', globals())
-
- def getId(self):
- return self.getClassAttr('id')
-
- def manage_edit(self, id, REQUEST=None):
- self.setClassAttr('id', id)
- if REQUEST is not None:
- return self.manage(self, REQUEST)
-
-
- class ZUniqueObjectPropertySheets(OFS.PropertySheets.PropertySheets):
-
- unique = UniqueSheet('unique')
-
- class ZUniqueObject:
- '''Mix-in for unique zclass instances.'''
-
- _zclass_ = UniqueObject
-
- propertysheets = ZUniqueObjectPropertySheets()
-
- manage_options = (
- {'label': 'Id', 'action':'propertysheets/unique/manage'},
- )