[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'},
-        )