Back to index

plone3  3.1.7
globalbrowsermenuservice.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001, 2002 Zope Corporation and Contributors.
00004 # All Rights Reserved.
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00008 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00009 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00010 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00011 # FOR A PARTICULAR PURPOSE.
00012 #
00013 ##############################################################################
00014 """Global Browser Menu Service
00015 
00016 Five-based adaptation of the one in Zope 3.0.
00017 
00018 $Id: globalbrowsermenuservice.py 38594 2005-09-24 15:51:32Z efge $
00019 """
00020 
00021 from zope.security.interfaces import Unauthorized, Forbidden
00022 from zope.interface import implementedBy
00023 from Products.Five.security import checkPermission, CheckerPublic
00024 from zope.app.publication.browser import PublicationTraverser
00025 from zope.app.component.interface import provideInterface
00026 
00027 from zope.app.publisher.browser.globalbrowsermenuservice import \
00028      globalBrowserMenuService
00029 from zope.app.publisher.browser.globalbrowsermenuservice import MenuItem
00030 
00031 from zope.interface.interfaces import IInterface
00032 from types import ClassType
00033 
00034 
00035 def addMenuItem(menu_id, interface, action, title,
00036                 description='', filter_string=None, permission=None,
00037                 extra=None,
00038                 ):
00039     registry = globalBrowserMenuService._registry[menu_id].registry
00040 
00041     if permission:
00042         if permission == 'zope.Public':
00043             permission = CheckerPublic
00044 
00045     if interface is not None and not IInterface.providedBy(interface):
00046         if isinstance(interface, (type, ClassType)):
00047             interface = implementedBy(interface)
00048         else:
00049             raise TypeError(
00050                 "The interface argument must be an interface (or None) "
00051                 "or a class.")
00052 
00053     data = registry.get(interface) or []
00054     data.append(
00055         MenuItem(action, title, description, filter_string, permission, extra)
00056         )
00057     registry.register(interface, data)
00058 
00059 
00060 def getMenu(menu_id, object, request, max=999999):
00061     traverser = PublicationTraverser()
00062 
00063     result = []
00064     seen = {}
00065 
00066     # stuff for figuring out the selected view
00067     request_url = request.getURL()
00068 
00069     for item in globalBrowserMenuService.getAllMenuItems(menu_id, object):
00070 
00071         # Make sure we don't repeat a specification for a given title
00072         title = item.title
00073         if title in seen:
00074             continue
00075         seen[title] = 1
00076 
00077         permission = item.permission
00078         action = item.action
00079 
00080         if permission:
00081             # If we have an explicit permission, check that we
00082             # can access it.
00083             if not checkPermission(permission, object):
00084                 continue
00085 
00086         elif action:
00087             # Otherwise, test access by attempting access
00088             path = action
00089             l = action.find('?')
00090             if l >= 0:
00091                path = action[:l]
00092             try:
00093                 v = traverser.traverseRelativeURL(
00094                     request, object, path)
00095                 # TODO:
00096                 # tickle the security proxy's checker
00097                 # we're assuming that view pages are callable
00098                 # this is a pretty sound assumption
00099                 v.__call__
00100             except (Unauthorized, Forbidden):
00101                 continue # Skip unauthorized or forbidden
00102 
00103         normalized_action = action
00104         if action.startswith('@@'):
00105             normalized_action = action[2:]
00106 
00107         if request_url.endswith('/'+normalized_action):
00108             selected='selected'
00109         elif request_url.endswith('/++view++'+normalized_action):
00110             selected='selected'
00111         elif request_url.endswith('/@@'+normalized_action):
00112             selected='selected'
00113         else:
00114             selected=''
00115 
00116         result.append({
00117             'title': title,
00118             'description': item.description,
00119             'action': "%s" % action,
00120             'filter': item.filter,
00121             'selected': selected,
00122             'extra': item.extra,
00123             })
00124 
00125         if len(result) >= max:
00126             return result
00127 
00128     return result
00129 
00130 
00131 
00132 def menuItemDirective(_context, menu, for_,
00133                       action, title, description='', filter=None,
00134                       permission=None, extra=None):
00135     return menuItemsDirective(_context, menu, for_).menuItem(
00136         _context, action, title, description, filter, permission, extra)
00137 
00138 
00139 class menuItemsDirective(object):
00140 
00141     def __init__(self, _context, menu, for_):
00142         self.interface = for_
00143         self.menu = menu
00144 
00145     def menuItem(self, _context, action, title, description='',
00146                  filter=None, permission=None, extra=None):
00147         _context.action(
00148             discriminator = ('browser:menuItem',
00149                              self.menu, self.interface, title),
00150             callable = addMenuItem,
00151             args = (self.menu, self.interface,
00152                     action, title, description, filter, permission, extra),
00153             ),
00154 
00155     def __call__(self, _context):
00156         _context.action(
00157             discriminator = None,
00158             callable = provideInterface,
00159             args = (self.interface.__module__+'.'+self.interface.getName(),
00160                     self.interface)
00161             )