[CMF-checkins] CVS: Products/CMFCore - ActionInformation.py:1.27 ActionsTool.py:1.55 __init__.py:1.31

Yvo Schubbe y.2005- at wcm-solutions.de
Tue Jan 25 14:50:11 EST 2005


Update of /cvs-repository/Products/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv24836/CMFCore

Modified Files:
	ActionInformation.py ActionsTool.py __init__.py 
Log Message:
merged yuppie-new_actions-branch:
- added ActionCategory and Action interfaces
- added ActionCategory and Action classes
- modified ActionsTool to make use of these new classes
- removed deprecated 'name' and 'permissions' keys from ActionInfo
- allowed 'description' key in ActionInfo
- implemented IAction in the oldstyle ActionInformation class and used this interface to simplify ActionInfo
- updated setup handlers, tests, default profile and skins
- fixed ActionInfo issue regarding permissions in oldstyle action dicts


=== Products/CMFCore/ActionInformation.py 1.26 => 1.27 ===
--- Products/CMFCore/ActionInformation.py:1.26	Thu Aug 12 11:07:39 2004
+++ Products/CMFCore/ActionInformation.py	Tue Jan 25 14:49:41 2005
@@ -20,69 +20,192 @@
 from AccessControl import ClassSecurityInfo
 from Acquisition import aq_base, aq_inner, aq_parent
 from Globals import InitializeClass
+from OFS.ObjectManager import IFAwareObjectManager
+from OFS.OrderedFolder import OrderedFolder
 from OFS.SimpleItem import SimpleItem
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 
-from interfaces.portal_actions import ActionInfo as IActionInfo
 from Expression import Expression
+from interfaces.portal_actions import Action as IAction
+from interfaces.portal_actions import ActionCategory as IActionCategory
+from interfaces.portal_actions import ActionInfo as IActionInfo
 from permissions import View
 from utils import _checkPermission
+from utils import _wwwdir
 from utils import getToolByName
+from utils import SimpleItemWithProperties
 
 
 _unchanged = [] # marker
 
+class ActionCategory(IFAwareObjectManager, OrderedFolder):
+    """ Group of Action objects.
+    """
+
+    __implements__ = (IActionCategory, OrderedFolder.__implements__)
+
+    meta_type = 'CMF Action Category'
+
+    _product_interfaces = (IActionCategory, IAction)
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('listActions')
+    def listActions(self):
+        """ List the actions defined in this category and its subcategories.
+        """
+        actions = []
+
+        for obj in self.objectValues():
+            if IActionCategory.isImplementedBy(obj):
+                actions.extend( obj.listActions() )
+            elif IAction.isImplementedBy(obj):
+                actions.append(obj)
+
+        return tuple(actions)
+
+InitializeClass(ActionCategory)
+
+manage_addActionCategoryForm = PageTemplateFile('addActionCategory.zpt',
+                                                _wwwdir)
+
+def manage_addActionCategory(self, id, REQUEST=None):
+    """Add a new CMF Action Category object with ID *id*.
+    """
+    obj = ActionCategory(id)
+    self._setObject(id, obj)
+
+    if REQUEST:
+        return self.manage_main(self, REQUEST, update_menu=1)
+
+
+class Action(SimpleItemWithProperties):
+    """ Reference to an action.
+    """
+
+    __implements__ = IAction
+
+    meta_type = 'CMF Action'
+
+    security = ClassSecurityInfo()
+
+    _properties = (
+        {'id': 'title', 'type': 'string', 'mode': 'w',
+         'label': 'Title'},
+        {'id': 'description', 'type': 'text', 'mode': 'w',
+         'label': 'Description'},
+        {'id': 'url_expr', 'type': 'string', 'mode': 'w',
+         'label': 'URL (Expression)'},
+        {'id': 'icon_expr', 'type': 'string', 'mode': 'w',
+         'label': 'Icon (Expression)'},
+        {'id': 'available_expr', 'type': 'string', 'mode': 'w',
+         'label': 'Condition (Expression)'},
+        {'id': 'permissions', 'type': 'multiple selection', 'mode': 'w',
+         'label': 'Permissions', 'select_variable': 'possible_permissions'},
+        {'id': 'visible', 'type': 'boolean', 'mode': 'w',
+         'label': 'Visible?'},
+        )
+
+    def __init__(self, id, **kw):
+        self.id = id
+        self._setPropValue( 'title', kw.get('title', '') )
+        self._setPropValue( 'description', kw.get('description', '') )
+        self._setPropValue( 'url_expr', kw.get('url_expr', '') )
+        self._setPropValue( 'icon_expr', kw.get('icon_expr', '') )
+        self._setPropValue( 'available_expr', kw.get('available_expr', '') )
+        self._setPropValue( 'permissions', kw.get('permissions', () ) )
+        self._setPropValue( 'visible', kw.get('visible', True) )
+
+    def _setPropValue(self, id, value):
+        self._wrapperCheck(value)
+        if isinstance(value, list):
+            value = tuple(value)
+        setattr(self, id, value)
+        if id.endswith('_expr'):
+            setattr( self, '%s_object' % id, Expression(value) )
+
+    security.declarePrivate('getInfoData')
+    def getInfoData(self):
+        """ Get the data needed to create an ActionInfo.
+        """
+        category_path = []
+        lazy_keys = []
+        lazy_map = {}
+
+        lazy_map['id'] = self.getId()
+
+        parent = aq_parent(self)
+        while parent is not None and parent.getId() != 'portal_actions':
+            category_path.append( parent.getId() )
+            parent = aq_parent(parent)
+        lazy_map['category'] = '/'.join(category_path[::-1])
+
+        for id, val in self.propertyItems():
+            if id.endswith('_expr'):
+                id = id[:-5]
+                if val:
+                    val = getattr(self, '%s_expr_object' % id)
+                    lazy_keys.append(id)
+                elif id == 'available':
+                    val = True
+            lazy_map[id] = val
+
+        return (lazy_map, lazy_keys)
+
+InitializeClass(Action)
+
+manage_addActionForm = PageTemplateFile( 'addAction.zpt', _wwwdir)
+
+def manage_addAction(self, id, REQUEST=None):
+    """Add a new CMF Action object with ID *id*.
+    """
+    obj = Action(id)
+    self._setObject(id, obj)
+
+    if REQUEST:
+        return self.manage_main(self, REQUEST)
+
+
 class ActionInfo(UserDict):
     """ A lazy dictionary for Action infos.
     """
+
     __implements__ = IActionInfo
+
     __allow_access_to_unprotected_subobjects__ = 1
 
     def __init__(self, action, ec):
-        lazy_keys = []
 
         if isinstance(action, dict):
+            lazy_keys = []
             UserDict.__init__(self, action)
-            self.data.setdefault( 'id', self.data['name'].lower() )
-            self.data.setdefault( 'title', self.data['name'] )
+            if 'name' in self.data:
+                self.data.setdefault( 'id', self.data['name'].lower() )
+                self.data.setdefault( 'title', self.data['name'] )
+                del self.data['name']
             self.data.setdefault( 'url', '' )
-            self.data.setdefault( 'permissions', () )
             self.data.setdefault( 'category', 'object' )
             self.data.setdefault( 'visible', True )
             self.data['available'] = True
-
         else:
-            self._action = action
-            self._ec = ec
-            UserDict.__init__( self, action.getMapping() )
-            self.data['name'] = self.data['title']
-            del self.data['description']
-
-            if self.data['action']:
-                self.data['url'] = self._getURL
-                lazy_keys.append('url')
-            else:
-                self.data['url'] = ''
-            del self.data['action']
-
-            if self.data['condition']:
-                self.data['available'] = self._checkCondition
-                lazy_keys.append('available')
-            else:
-                self.data['available'] = True
-            del self.data['condition']
-
-        if self.data['permissions']:
+            # if action isn't a dict, it has to implement IAction
+            (lazy_map, lazy_keys) = action.getInfoData()
+            UserDict.__init__(self, lazy_map)
+
+        self.data['allowed'] = True
+        permissions = self.data.pop( 'permissions', () )
+        if permissions:
             self.data['allowed'] = self._checkPermissions
             lazy_keys.append('allowed')
-        else:
-            self.data['allowed'] = True
 
+        self._ec = ec
         self._lazy_keys = lazy_keys
+        self._permissions = permissions
 
     def __getitem__(self, key):
         value = UserDict.__getitem__(self, key)
         if key in self._lazy_keys:
-            value = self.data[key] = value()
+            value = self.data[key] = value(self._ec)
             self._lazy_keys.remove(key)
         return value
 
@@ -98,32 +221,22 @@
         else:
             return self.data == 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):
+    def _checkPermissions(self, ec):
         """ Check permissions in the current context.
         """
         category = self['category']
-        object = self._ec.contexts['object']
+        object = ec.contexts['object']
         if object is not None and ( category.startswith('object') or
                                     category.startswith('workflow') ):
             context = object
         else:
-            folder = self._ec.contexts['folder']
+            folder = ec.contexts['folder']
             if folder is not None and category.startswith('folder'):
                 context = folder
             else:
-                context = self._ec.contexts['portal']
+                context = ec.contexts['portal']
 
-        for permission in self['permissions']:
+        for permission in self._permissions:
             if _checkPermission(permission, context):
                 return True
         return False
@@ -136,6 +249,9 @@
     Actions generate links to views of content, or to specific methods
     of the site.  They can be filtered via their conditions.
     """
+
+    __implements__ = IAction
+
     _isActionInformation = 1
     __allow_access_to_unprotected_subobjects__ = 1
 
@@ -322,6 +438,29 @@
         """ Get a newly-created AI just like us.
         """
         return self.__class__( priority=self.priority, **self.getMapping() )
+
+    security.declarePrivate('getInfoData')
+    def getInfoData(self):
+        """ Get the data needed to create an ActionInfo.
+        """
+        lazy_keys = []
+        lazy_map = self.getMapping()
+
+        if lazy_map['action']:
+            lazy_map['url'] = self._getActionObject()
+            lazy_keys.append('url')
+        else:
+            lazy_map['url'] = ''
+        del lazy_map['action']
+
+        if lazy_map['condition']:
+            lazy_map['available'] = self.testCondition
+            lazy_keys.append('available')
+        else:
+            lazy_map['available'] = True
+        del lazy_map['condition']
+
+        return (lazy_map, lazy_keys)
 
 InitializeClass( ActionInformation )
 


=== Products/CMFCore/ActionsTool.py 1.54 => 1.55 ===
--- Products/CMFCore/ActionsTool.py:1.54	Tue Sep 14 15:02:21 2004
+++ Products/CMFCore/ActionsTool.py	Tue Jan 25 14:49:41 2005
@@ -18,30 +18,34 @@
 from AccessControl import ClassSecurityInfo
 from Globals import DTMLFile
 from Globals import InitializeClass
-from OFS.Folder import Folder
+from OFS.ObjectManager import IFAwareObjectManager
+from OFS.OrderedFolder import OrderedFolder
 
 from ActionInformation import ActionInformation
 from ActionProviderBase import ActionProviderBase
 from Expression import Expression
+from interfaces.portal_actions import ActionCategory as IActionCategory
 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
 from utils import _dtmldir
-from utils import SimpleItemWithProperties
 from utils import UniqueObject
 
 
-class ActionsTool(UniqueObject, Folder, ActionProviderBase):
+class ActionsTool(UniqueObject, IFAwareObjectManager, OrderedFolder,
+                  ActionProviderBase):
     """
         Weave together the various sources of "actions" which are apropos
         to the current user and context.
     """
 
-    __implements__ = (IActionsTool, ActionProviderBase.__implements__)
+    __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(
@@ -68,15 +72,13 @@
 
     security = ClassSecurityInfo()
 
-    manage_options = ( ActionProviderBase.manage_options
-                     + ( { 'label' : 'Action Providers'
-                         , 'action' : 'manage_actionProviders'
-                         }
-                       , { 'label' : 'Overview'
-                         , 'action' : 'manage_overview'
-                         }
-                     ) + Folder.manage_options
-                     )
+    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
@@ -108,6 +110,34 @@
         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


=== Products/CMFCore/__init__.py 1.30 => 1.31 ===
--- Products/CMFCore/__init__.py:1.30	Sun Nov 28 16:40:27 2004
+++ Products/CMFCore/__init__.py	Tue Jan 25 14:49:41 2005
@@ -26,6 +26,7 @@
 import FSDTMLMethod, FSPythonScript, FSSTXMethod
 import FSPageTemplate
 import FSZSQLMethod
+import ActionInformation
 import CookieCrumbler
 import ContentTypeRegistry
 import CachingPolicyManager
@@ -99,6 +100,22 @@
         constructors=( CachingPolicyManager.manage_addCachingPolicyManager, ),
         icon = 'images/registry.gif'
         )
+
+    context.registerClass(
+        ActionInformation.ActionCategory,
+        permission=ManagePortal,
+        constructors=(ActionInformation.manage_addActionCategoryForm,
+                      ActionInformation.manage_addActionCategory),
+        icon='images/cmf_action_category.gif',
+        visibility=None)
+
+    context.registerClass(
+        ActionInformation.Action,
+        permission=ManagePortal,
+        constructors=(ActionInformation.manage_addActionForm,
+                      ActionInformation.manage_addAction),
+        icon='images/cmf_action.gif',
+        visibility=None)
 
     context.registerClass(
         TypesTool.FactoryTypeInformation,



More information about the CMF-checkins mailing list