[Zope3-checkins] CVS: Zope3/src/zope/app/publisher/browser - globalbrowsermenuservice.py:1.21.4.2

Stephan Richter srichter at cosmos.phy.tufts.edu
Thu Aug 14 14:58:39 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app/publisher/browser
In directory cvs.zope.org:/tmp/cvs-serv10819/app/publisher/browser

Modified Files:
      Tag: dreamcatcher-ttwschema-branch
	globalbrowsermenuservice.py 
Log Message:
Checkpoint check-in for people following the branch:

Got Local Browser Menu Service to work. I used a similar model to the 
interface service, where the service uses registered Browser Menu utilities
to get its menu entries.

There are also a bunch of policy-type decisions that come with local menus.
One is whether a local menu should overwrite or complement existing menus.
Currently I have an 'inherit' flag that can be set. If true, the local menu
will add to the existing entries, otherwise it will overwrite them. Note 
that this does not solve all use cases, such as if you want to take over
just a few entries, but I called YAGNI on it (someone else can do it, if it
is necessary).

I added and extended interfaces for all of this to work. I tried really 
hard to avoid rewriting the getMenu() methof for the local menu service 
version and I think I got it. ;-)

I also have a nice Overview screen for the Local Menu Service, which shows
you all available menus.

To Do:

  - Flesh out the interfaces and implement missing methods.

  - Clean up the code.

  - Fix tests.

  - Write a bunch of new tests.




=== Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py 1.21.4.1 => 1.21.4.2 ===
--- Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py:1.21.4.1	Wed Aug 13 09:36:28 2003
+++ Zope3/src/zope/app/publisher/browser/globalbrowsermenuservice.py	Thu Aug 14 13:58:05 2003
@@ -11,6 +11,10 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
+"""Global Browser Menu Service
+
+$Id$
+"""
 
 from zope.interface import classProvides
 from zope.exceptions import DuplicationError, Unauthorized, Forbidden
@@ -26,13 +30,15 @@
 from zope.app.security.permission import checkPermission
 
 from zope.app.component.metaconfigure import handler
-from zope.app.interfaces.publisher.browser import IBrowserMenuService
+from zope.app.interfaces.publisher.browser import \
+     IBrowserMenuService, IGlobalBrowserMenuService, IBrowserMenu
 from zope.app.pagetemplate.engine import Engine
 from zope.app.publication.browser import PublicationTraverser
 
 class Menu(object):
-    '''Browser menu
-    '''
+    """Browser menu"""
+
+    implements(IBrowserMenu)
 
     def __init__(self, title, description=u'', usage=u''):
         self.title = title
@@ -40,16 +46,130 @@
         self.usage = usage
         self.registry = TypeRegistry()
 
+    def getMenuItems(self, object=None):
+        """See zope.app.interfaces.publisher.browser.IMenuItem"""
+        results = []
+        if object is None:
+            for items in self.registry._reg.values():
+                results += items
+        else:
+            for items in self.registry.getAllForObject(object):
+                results += items
+        return results
+
 
-class GlobalBrowserMenuService(object):
-    """Global Browser Menu Service
-    """
+class BaseBrowserMenuService(object):
+    """Global Browser Menu Service"""
 
     implements(IBrowserMenuService)
 
     def __init__(self):
         self._registry = {}
 
+    def getAllMenuItems(self, menu_id, object):
+        return self._registry[menu_id].getMenuItems(object)
+
+    def getMenu(self, menu_id, object, request, max=999999):
+        traverser = PublicationTraverser()
+
+        result = []
+        seen = {}
+        sm = getSecurityManager()
+
+        # stuff for figuring out the selected view
+        request_url = request.getURL()
+
+        for items in self.getAllMenuItems(menu_id, object):
+            action, title, description, filter, permission = items
+
+            # Make sure we don't repeat a specification for a given title
+            if title in seen:
+                continue
+            seen[title] = 1
+            
+            if filter is not None:
+            
+                try:
+                    include = filter(Engine.getContext(
+                        context = object,
+                        nothing = None,
+                        request = request,
+                        ))
+                except Unauthorized:
+                    include = 0
+            
+                if not include:
+                    continue
+            
+            if permission:
+                # If we have an explicit permission, check that we
+                # can access it.
+                if not sm.checkPermission(permission, object) and \
+                       permission is not CheckerPublic:
+                    continue
+            
+            elif action:
+                # Otherwise, test access by attempting access
+                path = action
+                l = action.find('?')
+                if l >= 0:
+                   path = action[:l] 
+                try:
+                    v = traverser.traverseRelativeURL(
+                        request, object, path)
+                    # XXX
+                    # tickle the security proxy's checker
+                    # we're assuming that view pages are callable
+                    # this is a pretty sound assumption
+                    v.__call__
+                except (Unauthorized, Forbidden):
+                    continue # Skip unauthorized or forbidden
+
+            normalized_action = action
+            if action.startswith('@@'):
+                normalized_action = action[2:]
+            
+            if request_url.endswith(action):
+                selected='selected'
+            elif request_url.endswith('/'+normalized_action):
+                selected='selected'
+            elif request_url.endswith('++view++'+normalized_action):
+                selected='selected'
+            else:
+                selected=''
+
+            result.append({
+                'title': title,
+                'description': description,
+                'action': "%s" % action,
+                'selected': selected
+                })
+            
+            if len(result) >= max:
+                return result
+
+        return result
+
+    def getMenuUsage(self, menu_id):
+        return self._registry[menu_id].usage
+        
+
+    def getFirstMenuItem(self, menu_id, object, request):
+        r = self.getMenu(menu_id, object, request, max=1)
+        if r:
+            return r[0]
+        return None
+
+
+class GlobalBrowserMenuService(BaseBrowserMenuService):
+    """Global Browser Menu Service that can be manipulated by adding new menus
+    and menu entries."""
+
+    implements(IGlobalBrowserMenuService)
+
+    def __init__(self):
+        self._registry = {}
+
     _clear = __init__
 
     def menu(self, menu_id, title, description=u'', usage=u''):
@@ -81,96 +201,6 @@
         data.append((action, title, description, filter, permission))
         registry.register(interface, data)
 
-    def getMenu(self, menu_id, object, request, max=999999):
-        registry = self._registry[menu_id].registry
-        traverser = PublicationTraverser()
-
-        result = []
-        seen = {}
-        sm = getSecurityManager()
-
-        # stuff for figuring out the selected view
-        request_url = request.getURL()
-
-        for items in registry.getAllForObject(object):
-            for action, title, description, filter, permission in items:
-
-                # Make sure we don't repeat a specification for a given title
-                if title in seen:
-                    continue
-                seen[title] = 1
-
-                if filter is not None:
-
-                    try:
-                        include = filter(Engine.getContext(
-                            context = object,
-                            nothing = None,
-                            request = request,
-                            ))
-                    except Unauthorized:
-                        include = 0
-
-                    if not include:
-                        continue
-
-                if permission:
-                    # If we have an explicit permission, check that we
-                    # can access it.
-                    if not sm.checkPermission(permission, object):
-                        continue
-
-                elif action:
-                    # Otherwise, test access by attempting access
-                    path = action
-                    l = action.find('?')
-                    if l >= 0:
-                       path = action[:l] 
-                    try:
-                        v = traverser.traverseRelativeURL(
-                            request, object, path)
-                        # XXX
-                        # tickle the security proxy's checker
-                        # we're assuming that view pages are callable
-                        # this is a pretty sound assumption
-                        v.__call__
-                    except (Unauthorized, Forbidden):
-                        continue # Skip unauthorized or forbidden
-
-                normalized_action = action
-                if action.startswith('@@'):
-                    normalized_action = action[2:]
-
-                if request_url.endswith(action):
-                    selected='selected'
-                elif request_url.endswith('/'+normalized_action):
-                    selected='selected'
-                elif request_url.endswith('++view++'+normalized_action):
-                    selected='selected'
-                else:
-                    selected=''
-
-                result.append({
-                    'title': title,
-                    'description': description,
-                    'action': "%s" % action,
-                    'selected': selected
-                    })
-
-                if len(result) >= max:
-                    return result
-
-        return result
-
-    def getMenuUsage(self, menu_id):
-        return self._registry[menu_id].usage
-        
-
-    def getFirstMenuItem(self, menu_id, object, request):
-        r = self.getMenu(menu_id, object, request, max=1)
-        if r:
-            return r[0]
-        return None
 
 def menuDirective(_context, id, title, description='', usage=u''):
     _context.action(
@@ -219,8 +249,3 @@
 from zope.testing.cleanup import addCleanUp
 addCleanUp(_clear)
 del addCleanUp
-
-__doc__ = GlobalBrowserMenuService.__doc__ + """
-
-$Id$
-"""




More information about the Zope3-Checkins mailing list