Back to index

plone3  3.1.7
TypesTool.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Type registration tool.
00014 
00015 $Id: TypesTool.py 77288 2007-07-02 07:29:27Z hannosch $
00016 """
00017 
00018 import logging
00019 from warnings import warn
00020 
00021 import Products
00022 from AccessControl import ClassSecurityInfo
00023 from AccessControl import getSecurityManager
00024 from Acquisition import aq_base
00025 from Acquisition import aq_get
00026 from Globals import DTMLFile
00027 from Globals import InitializeClass
00028 from OFS.Folder import Folder
00029 from OFS.ObjectManager import IFAwareObjectManager
00030 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
00031 from zope.component import getUtility
00032 from zope.component import queryUtility
00033 from zope.component.interfaces import IFactory
00034 from zope.i18nmessageid import Message
00035 from zope.interface import implements
00036 
00037 from ActionProviderBase import ActionProviderBase
00038 from exceptions import AccessControl_Unauthorized
00039 from exceptions import BadRequest
00040 from exceptions import zExceptions_Unauthorized
00041 from interfaces import ITypeInformation
00042 from interfaces import ITypesTool
00043 from interfaces.portal_types \
00044         import ContentTypeInformation as z2ITypeInformation
00045 from interfaces.portal_types import portal_types as z2ITypesTool
00046 from permissions import AccessContentsInformation
00047 from permissions import ManagePortal
00048 from permissions import View
00049 from utils import _checkPermission
00050 from utils import _dtmldir
00051 from utils import _wwwdir
00052 from utils import SimpleItemWithProperties
00053 from utils import UniqueObject
00054 
00055 logger = logging.getLogger('CMFCore.TypesTool')
00056 
00057 _marker = []  # Create a new marker.
00058 
00059 
00060 class TypeInformation(SimpleItemWithProperties, ActionProviderBase):
00061 
00062     """ Base class for information about a content type.
00063     """
00064 
00065     manage_options = ( SimpleItemWithProperties.manage_options[:1]
00066                      + ( {'label':'Aliases',
00067                           'action':'manage_aliases'}, )
00068                      + ActionProviderBase.manage_options
00069                      + SimpleItemWithProperties.manage_options[1:]
00070                      )
00071 
00072     security = ClassSecurityInfo()
00073 
00074     security.declareProtected(ManagePortal, 'manage_editProperties')
00075     security.declareProtected(ManagePortal, 'manage_changeProperties')
00076     security.declareProtected(ManagePortal, 'manage_propertiesForm')
00077 
00078     _basic_properties = (
00079         {'id':'title', 'type': 'string', 'mode':'w',
00080          'label':'Title'},
00081         {'id':'description', 'type': 'text', 'mode':'w',
00082          'label':'Description'},
00083         {'id':'i18n_domain', 'type': 'string', 'mode':'w',
00084          'label':'I18n Domain'},
00085         {'id':'content_icon', 'type': 'string', 'mode':'w',
00086          'label':'Icon'},
00087         {'id':'content_meta_type', 'type': 'string', 'mode':'w',
00088          'label':'Product meta type'},
00089         )
00090 
00091     _advanced_properties = (
00092         {'id':'immediate_view', 'type': 'string', 'mode':'w',
00093          'label':'Initial view name'},
00094         {'id':'global_allow', 'type': 'boolean', 'mode':'w',
00095          'label':'Implicitly addable?'},
00096         {'id':'filter_content_types', 'type': 'boolean', 'mode':'w',
00097          'label':'Filter content types?'},
00098         {'id':'allowed_content_types'
00099          , 'type': 'multiple selection'
00100          , 'mode':'w'
00101          , 'label':'Allowed content types'
00102          , 'select_variable':'listContentTypes'
00103          },
00104         { 'id': 'allow_discussion', 'type': 'boolean', 'mode': 'w'
00105           , 'label': 'Allow Discussion?'
00106           },
00107         )
00108 
00109     title = ''
00110     description = ''
00111     i18n_domain = ''
00112     content_meta_type = ''
00113     content_icon = ''
00114     immediate_view = ''
00115     filter_content_types = True
00116     allowed_content_types = ()
00117     allow_discussion = False
00118     global_allow = True
00119 
00120     def __init__(self, id, **kw):
00121 
00122         self.id = id
00123         self._actions = ()
00124         self._aliases = {}
00125 
00126         if not kw:
00127             return
00128 
00129         kw = kw.copy()  # Get a modifiable dict.
00130 
00131         if (not kw.has_key('content_meta_type')
00132             and kw.has_key('meta_type')):
00133             kw['content_meta_type'] = kw['meta_type']
00134 
00135         if (not kw.has_key('content_icon')
00136             and kw.has_key('icon')):
00137             kw['content_icon'] = kw['icon']
00138 
00139         self.manage_changeProperties(**kw)
00140 
00141         actions = kw.get( 'actions', () )
00142         for action in actions:
00143             self.addAction(
00144                   id=action['id']
00145                 , name=action['title']
00146                 , action=action['action']
00147                 , condition=action.get('condition')
00148                 , permission=action.get( 'permissions', () )
00149                 , category=action.get('category', 'object')
00150                 , visible=action.get('visible', True)
00151                 )
00152 
00153         self.setMethodAliases(kw.get('aliases', {}))
00154 
00155     #
00156     #   ZMI methods
00157     #
00158     security.declareProtected(ManagePortal, 'manage_aliases')
00159     manage_aliases = PageTemplateFile( 'typeinfoAliases.zpt', _wwwdir )
00160 
00161     security.declareProtected(ManagePortal, 'manage_setMethodAliases')
00162     def manage_setMethodAliases(self, REQUEST):
00163         """ Config method aliases.
00164         """
00165         form = REQUEST.form
00166         aliases = {}
00167         for k, v in form['aliases'].items():
00168             v = v.strip()
00169             if v:
00170                 aliases[k] = v
00171 
00172         _dict = {}
00173         for k, v in form['methods'].items():
00174             if aliases.has_key(k):
00175                 _dict[ aliases[k] ] = v
00176         self.setMethodAliases(_dict)
00177         REQUEST.RESPONSE.redirect('%s/manage_aliases' % self.absolute_url())
00178 
00179     #
00180     #   Accessors
00181     #
00182     security.declareProtected(View, 'Title')
00183     def Title(self):
00184         """
00185             Return the "human readable" type name (note that it
00186             may not map exactly to the 'portal_type', e.g., for
00187             l10n/i18n or where a single content class is being
00188             used twice, under different names.
00189         """
00190         if self.title and self.i18n_domain:
00191             return Message(self.title, self.i18n_domain)
00192         else:
00193             return self.title or self.getId()
00194 
00195     security.declareProtected(View, 'Description')
00196     def Description(self):
00197         """
00198             Textual description of the class of objects (intended
00199             for display in a "constructor list").
00200         """
00201         if self.description and self.i18n_domain:
00202             return Message(self.description, self.i18n_domain)
00203         else:
00204             return self.description
00205 
00206     security.declareProtected(View, 'Metatype')
00207     def Metatype(self):
00208         """
00209             Returns the Zope 'meta_type' for this content object.
00210             May be used for building the list of portal content
00211             meta types.
00212         """
00213         return self.content_meta_type
00214 
00215     security.declareProtected(View, 'getIcon')
00216     def getIcon(self):
00217         """
00218             Returns the icon for this content object.
00219         """
00220         return self.content_icon
00221 
00222     security.declarePublic('allowType')
00223     def allowType( self, contentType ):
00224         """
00225             Can objects of 'contentType' be added to containers whose
00226             type object we are?
00227         """
00228         if not self.filter_content_types:
00229             ti = self.getTypeInfo( contentType )
00230             if ti is None or ti.globalAllow():
00231                 return 1
00232 
00233         #If a type is enabled to filter and no content_types are allowed
00234         if not self.allowed_content_types:
00235             return 0
00236 
00237         if contentType in self.allowed_content_types:
00238             return 1
00239 
00240         return 0
00241 
00242     security.declarePublic('getId')
00243     def getId(self):
00244         return self.id
00245 
00246     security.declarePublic('allowDiscussion')
00247     def allowDiscussion( self ):
00248         """
00249             Can this type of object support discussion?
00250         """
00251         return self.allow_discussion
00252 
00253     security.declarePublic('globalAllow')
00254     def globalAllow(self):
00255         """
00256         Should this type be implicitly addable anywhere?
00257         """
00258         return self.global_allow
00259 
00260     security.declarePublic('listActions')
00261     def listActions(self, info=None, object=None):
00262         """ Return a sequence of the action info objects for this type.
00263         """
00264         return self._actions or ()
00265 
00266     security.declarePublic('constructInstance')
00267     def constructInstance(self, container, id, *args, **kw):
00268         """Build an instance of the type.
00269 
00270         Builds the instance in 'container', using 'id' as its id.
00271         Returns the object.
00272         """
00273         if not self.isConstructionAllowed(container):
00274             raise AccessControl_Unauthorized('Cannot create %s' % self.getId())
00275 
00276         ob = self._constructInstance(container, id, *args, **kw)
00277 
00278         return self._finishConstruction(ob)
00279 
00280     security.declarePrivate('_finishConstruction')
00281     def _finishConstruction(self, ob):
00282         """
00283             Finish the construction of a content object.
00284             Set its portal_type, insert it into the workflows.
00285         """
00286         if hasattr(ob, '_setPortalTypeName'):
00287             ob._setPortalTypeName(self.getId())
00288 
00289         if hasattr(aq_base(ob), 'notifyWorkflowCreated'):
00290             ob.notifyWorkflowCreated()
00291 
00292         ob.reindexObject()
00293         return ob
00294 
00295     security.declareProtected(ManagePortal, 'getMethodAliases')
00296     def getMethodAliases(self):
00297         """ Get method aliases dict.
00298         """
00299         aliases = self._aliases
00300         # for aliases created with CMF 1.5.0beta
00301         for key, method_id in aliases.items():
00302             if isinstance(method_id, tuple):
00303                 aliases[key] = method_id[0]
00304                 self._p_changed = True
00305         return aliases.copy()
00306 
00307     security.declareProtected(ManagePortal, 'setMethodAliases')
00308     def setMethodAliases(self, aliases):
00309         """ Set method aliases dict.
00310         """
00311         _dict = {}
00312         for k, v in aliases.items():
00313             v = v.strip()
00314             if v:
00315                 _dict[ k.strip() ] = v
00316         if not getattr(self, '_aliases', None) == _dict:
00317             self._aliases = _dict
00318             return True
00319         else:
00320             return False
00321 
00322     security.declarePublic('queryMethodID')
00323     def queryMethodID(self, alias, default=None, context=None):
00324         """ Query method ID by alias.
00325         """
00326         aliases = self._aliases
00327         method_id = aliases.get(alias, default)
00328         # for aliases created with CMF 1.5.0beta
00329         if isinstance(method_id, tuple):
00330             method_id = method_id[0]
00331         return method_id
00332 
00333 InitializeClass(TypeInformation)
00334 
00335 
00336 class FactoryTypeInformation(TypeInformation):
00337 
00338     """ Portal content factory.
00339     """
00340 
00341     implements(ITypeInformation)
00342     __implements__ = z2ITypeInformation
00343 
00344     security = ClassSecurityInfo()
00345 
00346     _properties = (TypeInformation._basic_properties + (
00347         {'id':'product', 'type': 'string', 'mode':'w',
00348          'label':'Product name'},
00349         {'id':'factory', 'type': 'string', 'mode':'w',
00350          'label':'Product factory'},
00351         ) + TypeInformation._advanced_properties)
00352 
00353     product = ''
00354     factory = ''
00355 
00356     #
00357     #   Agent methods
00358     #
00359     def _getFactoryMethod(self, container, check_security=1):
00360         if not self.product or not self.factory:
00361             raise ValueError, ('Product factory for %s was undefined' %
00362                                self.getId())
00363         p = container.manage_addProduct[self.product]
00364         m = getattr(p, self.factory, None)
00365         if m is None:
00366             raise ValueError, ('Product factory for %s was invalid' %
00367                                self.getId())
00368         if not check_security:
00369             return m
00370         if getSecurityManager().validate(p, p, self.factory, m):
00371             return m
00372         raise AccessControl_Unauthorized( 'Cannot create %s' % self.getId() )
00373 
00374     def _queryFactoryMethod(self, container, default=None):
00375 
00376         if not self.product or not self.factory or container is None:
00377             return default
00378 
00379         # In case we aren't wrapped.
00380         dispatcher = getattr(container, 'manage_addProduct', None)
00381 
00382         if dispatcher is None:
00383             return default
00384 
00385         try:
00386             p = dispatcher[self.product]
00387         except AttributeError:
00388             logger.exception("_queryFactoryMethod raised an exception")
00389             return default
00390 
00391         m = getattr(p, self.factory, None)
00392 
00393         if m:
00394             try:
00395                 # validate() can either raise Unauthorized or return 0 to
00396                 # mean unauthorized.
00397                 if getSecurityManager().validate(p, p, self.factory, m):
00398                     return m
00399             except zExceptions_Unauthorized:  # Catch *all* Unauths!
00400                 pass
00401 
00402         return default
00403 
00404     security.declarePublic('isConstructionAllowed')
00405     def isConstructionAllowed(self, container):
00406         """
00407         a. Does the factory method exist?
00408 
00409         b. Is the factory method usable?
00410 
00411         c. Does the current user have the permission required in
00412         order to invoke the factory method?
00413         """
00414         if self.product:
00415             # oldstyle factory
00416             m = self._queryFactoryMethod(container)
00417             return (m is not None)
00418 
00419         elif container is not None:
00420             # newstyle factory
00421             m = queryUtility(IFactory, self.factory, None)
00422             if m is not None:
00423                 for d in container.all_meta_types():
00424                     if d['name'] == self.content_meta_type:
00425                         sm = getSecurityManager()
00426                         return sm.checkPermission(d['permission'], container)
00427 
00428         return False
00429 
00430     security.declarePrivate('_constructInstance')
00431     def _constructInstance(self, container, id, *args, **kw):
00432         """Build a bare instance of the appropriate type.
00433 
00434         Does not do any security checks.
00435 
00436         Returns the object without calling _finishConstruction().
00437         """
00438         # XXX: this method violates the rules for tools/utilities:
00439         # it depends on self.REQUEST
00440         id = str(id)
00441 
00442         if self.product:
00443             # oldstyle factory
00444             m = self._getFactoryMethod(container, check_security=0)
00445 
00446             if getattr(aq_base(m), 'isDocTemp', 0):
00447                 kw['id'] = id
00448                 newid = m(m.aq_parent, self.REQUEST, *args, **kw)
00449             else:
00450                 newid = m(id, *args, **kw)
00451             # allow factory to munge ID
00452             newid = newid or id
00453 
00454         else:
00455             # newstyle factory
00456             factory = getUtility(IFactory, self.factory)
00457             obj = factory(id, *args, **kw)
00458             rval = container._setObject(id, obj)
00459             newid = isinstance(rval, basestring) and rval or id
00460 
00461         return container._getOb(newid)
00462 
00463 InitializeClass(FactoryTypeInformation)
00464 
00465 
00466 class ScriptableTypeInformation(TypeInformation):
00467 
00468     """ Invokes a script rather than a factory to create the content.
00469     """
00470 
00471     implements(ITypeInformation)
00472     __implements__ = z2ITypeInformation
00473 
00474     security = ClassSecurityInfo()
00475 
00476     _properties = (TypeInformation._basic_properties + (
00477         {'id':'permission', 'type': 'string', 'mode':'w',
00478          'label':'Constructor permission'},
00479         {'id':'constructor_path', 'type': 'string', 'mode':'w',
00480          'label':'Constructor path'},
00481         ) + TypeInformation._advanced_properties)
00482 
00483     permission = ''
00484     constructor_path = ''
00485 
00486     #
00487     #   Agent methods
00488     #
00489     security.declarePublic('isConstructionAllowed')
00490     def isConstructionAllowed(self, container):
00491         """
00492         Does the current user have the permission required in
00493         order to construct an instance?
00494         """
00495         permission = self.permission
00496         if permission and not _checkPermission( permission, container ):
00497             return 0
00498         return 1
00499 
00500     security.declarePrivate('_constructInstance')
00501     def _constructInstance(self, container, id, *args, **kw):
00502         """Build a bare instance of the appropriate type.
00503 
00504         Does not do any security checks.
00505 
00506         Returns the object without calling _finishConstruction().
00507         """
00508         constructor = self.restrictedTraverse( self.constructor_path )
00509 
00510         # make sure ownership is explicit before switching the context
00511         if not hasattr( aq_base(constructor), '_owner' ):
00512             constructor._owner = aq_get(constructor, '_owner')
00513         #   Rewrap to get into container's context.
00514         constructor = aq_base(constructor).__of__( container )
00515 
00516         id = str(id)
00517         return constructor(container, id, *args, **kw)
00518 
00519 InitializeClass(ScriptableTypeInformation)
00520 
00521 
00522 allowedTypes = [
00523     'Script (Python)',
00524     'Python Method',
00525     'DTML Method',
00526     'External Method',
00527     ]
00528 
00529 
00530 class TypesTool(UniqueObject, IFAwareObjectManager, Folder,
00531                 ActionProviderBase):
00532 
00533     """ Provides a configurable registry of portal content types.
00534     """
00535 
00536     implements(ITypesTool)
00537     __implements__ = (z2ITypesTool, ActionProviderBase.__implements__)
00538 
00539     id = 'portal_types'
00540     meta_type = 'CMF Types Tool'
00541     _product_interfaces = (ITypeInformation,)
00542 
00543     security = ClassSecurityInfo()
00544 
00545     manage_options = ( Folder.manage_options[:1]
00546                      + ( {'label':'Aliases',
00547                           'action':'manage_aliases'}, )
00548                      + ActionProviderBase.manage_options
00549                      + ( {'label':'Overview',
00550                           'action':'manage_overview'}, )
00551                      + Folder.manage_options[1:]
00552                      )
00553 
00554     #
00555     #   ZMI methods
00556     #
00557     security.declareProtected(ManagePortal, 'manage_overview')
00558     manage_overview = DTMLFile( 'explainTypesTool', _dtmldir )
00559 
00560     security.declareProtected(ManagePortal, 'manage_aliases')
00561     manage_aliases = PageTemplateFile( 'typesAliases.zpt', _wwwdir )
00562 
00563     #
00564     #   ObjectManager methods
00565     #
00566     def all_meta_types(self, interfaces=None):
00567         # this is a workaround and should be removed again if allowedTypes
00568         # have an interface we can use in _product_interfaces
00569         all = TypesTool.inheritedAttribute('all_meta_types')(self)
00570         others = [ mt for mt in Products.meta_types
00571                    if mt['name'] in allowedTypes ]
00572         return tuple(all) + tuple(others)
00573 
00574     #
00575     #   other methods
00576     #
00577     security.declareProtected(ManagePortal, 'manage_addTypeInformation')
00578     def manage_addTypeInformation(self, add_meta_type, id=None,
00579                                   typeinfo_name=None, RESPONSE=None):
00580         """Create a TypeInformation in self.
00581         """
00582         # BBB: typeinfo_name is ignored
00583         if not id:
00584             raise BadRequest('An id is required.')
00585         for mt in Products.meta_types:
00586             if mt['name'] == add_meta_type:
00587                 klass = mt['instance']
00588                 break
00589         else:
00590             raise ValueError, (
00591                 'Meta type %s is not a type class.' % add_meta_type)
00592         id = str(id)
00593         ob = klass(id)
00594         self._setObject(id, ob)
00595         if RESPONSE is not None:
00596             RESPONSE.redirect('%s/manage_main' % self.absolute_url())
00597 
00598     security.declareProtected(ManagePortal, 'manage_setTIMethodAliases')
00599     def manage_setTIMethodAliases(self, REQUEST):
00600         """ Config method aliases.
00601         """
00602         form = REQUEST.form
00603         aliases = {}
00604         for k, v in form['aliases'].items():
00605             v = v.strip()
00606             if v:
00607                 aliases[k] = v
00608 
00609         for ti in self.listTypeInfo():
00610             _dict = {}
00611             for k, v in form[ ti.getId() ].items():
00612                 if aliases.has_key(k):
00613                     _dict[ aliases[k] ] = v
00614             ti.setMethodAliases(_dict)
00615         REQUEST.RESPONSE.redirect('%s/manage_aliases' % self.absolute_url())
00616 
00617     security.declareProtected(AccessContentsInformation, 'getTypeInfo')
00618     def getTypeInfo( self, contentType ):
00619         """
00620             Return an instance which implements the
00621             TypeInformation interface, corresponding to
00622             the specified 'contentType'.  If contentType is actually
00623             an object, rather than a string, attempt to look up
00624             the appropriate type info using its portal_type.
00625         """
00626         if not isinstance(contentType, basestring):
00627             if hasattr(aq_base(contentType), 'getPortalTypeName'):
00628                 contentType = contentType.getPortalTypeName()
00629                 if contentType is None:
00630                     return None
00631             else:
00632                 return None
00633         ob = getattr( self, contentType, None )
00634         if ITypeInformation.providedBy(ob):
00635             return ob
00636         if getattr(aq_base(ob), '_isTypeInformation', 0):
00637             # BBB
00638             warn("The '_isTypeInformation' marker attribute is deprecated, "
00639                  "and will be removed in CMF 2.3.  Please mark the instance "
00640                  "with the 'ITypeInformation' interface instead.",
00641                  DeprecationWarning, stacklevel=2)
00642             return ob
00643         else:
00644             return None
00645 
00646     security.declareProtected(AccessContentsInformation, 'listTypeInfo')
00647     def listTypeInfo( self, container=None ):
00648         """
00649             Return a sequence of instances which implement the
00650             TypeInformation interface, one for each content
00651             type registered in the portal.
00652         """
00653         rval = []
00654         for t in self.objectValues():
00655             # Filter out things that aren't TypeInformation and
00656             # types for which the user does not have adequate permission.
00657             if ITypeInformation.providedBy(t):
00658                 rval.append(t)
00659             elif getattr(aq_base(t), '_isTypeInformation', 0):
00660                 # BBB
00661                 warn("The '_isTypeInformation' marker attribute is deprecated, "
00662                      "and will be removed in CMF 2.3.  Please mark the "
00663                      "instance with the 'ITypeInformation' interface instead.",
00664                      DeprecationWarning, stacklevel=2)
00665                 rval.append(t)
00666         # Skip items with no ID:  old signal for "not ready"
00667         rval = [t for t in rval if t.getId()]
00668         # check we're allowed to access the type object
00669         if container is not None:
00670             rval = [t for t in rval if t.isConstructionAllowed(container)]
00671         return rval
00672 
00673     security.declareProtected(AccessContentsInformation, 'listContentTypes')
00674     def listContentTypes(self, container=None, by_metatype=0):
00675         """ List type info IDs.
00676 
00677         Passing 'by_metatype' is deprecated (type information may not
00678         correspond 1:1 to an underlying meta_type). This argument will be
00679         removed when CMFCore/dtml/catalogFind.dtml doesn't need it anymore.
00680         """
00681         typenames = {}
00682         for t in self.listTypeInfo( container ):
00683 
00684             if by_metatype:
00685                 warn('TypeInformation.listContentTypes(by_metatype=1) is '
00686                      'deprecated.',
00687                      DeprecationWarning)
00688                 name = t.Metatype()
00689             else:
00690                 name = t.getId()
00691 
00692             if name:
00693                 typenames[ name ] = None
00694 
00695         result = typenames.keys()
00696         result.sort()
00697         return result
00698 
00699     security.declarePublic('constructContent')
00700     def constructContent( self
00701                         , type_name
00702                         , container
00703                         , id
00704                         , RESPONSE=None
00705                         , *args
00706                         , **kw
00707                         ):
00708         """
00709             Build an instance of the appropriate content class in
00710             'container', using 'id'.
00711         """
00712         info = self.getTypeInfo( type_name )
00713         if info is None:
00714             raise ValueError('No such content type: %s' % type_name)
00715 
00716         ob = info.constructInstance(container, id, *args, **kw)
00717 
00718         if RESPONSE is not None:
00719             immediate_url = '%s/%s' % ( ob.absolute_url()
00720                                       , info.immediate_view )
00721             RESPONSE.redirect( immediate_url )
00722 
00723         return ob.getId()
00724 
00725     security.declarePrivate( 'listActions' )
00726     def listActions(self, info=None, object=None):
00727         """ List all the actions defined by a provider.
00728         """
00729         actions = list( self._actions )
00730 
00731         if object is None and info is not None:
00732             object = info.object
00733         if object is not None:
00734             type_info = self.getTypeInfo(object)
00735             if type_info is not None:
00736                 actions.extend( type_info.listActions(info, object) )
00737 
00738         return actions
00739 
00740     security.declareProtected(ManagePortal, 'listMethodAliasKeys')
00741     def listMethodAliasKeys(self):
00742         """ List all defined method alias names.
00743         """
00744         _dict = {}
00745         for ti in self.listTypeInfo():
00746             aliases = ti.getMethodAliases()
00747             for k, v in aliases.items():
00748                 _dict[k] = 1
00749         rval = _dict.keys()
00750         rval.sort()
00751         return rval
00752 
00753 InitializeClass(TypesTool)