Skip to content

Commit

Permalink
Fix up zope.app according to new location of BrowserView.
Browse files Browse the repository at this point in the history
  • Loading branch information
philikon committed Apr 6, 2006
1 parent ab92a5d commit 3d5e100
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 9 deletions.
113 changes: 113 additions & 0 deletions browser/directoryresource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Resource Directory
A 'resource directory' is an on-disk directory which is registered as
a resource using the <resourceDirectory> ZCML directive. The
directory is treated as a source for individual resources; it can be
traversed to retrieve resources represented by contained files, which
can in turn be treated as resources. The contained files have
__name__ values which include a '/' separating the __name__ of the
resource directory from the name of the file within the directory.
$Id$
"""
import os
import posixpath

from zope.interface import implements
from zope.publisher.interfaces import NotFound
from zope.security.proxy import Proxy
from zope.publisher.browser import BrowserView
from zope.publisher.interfaces.browser import IBrowserPublisher

from zope.app.publisher.browser.resource import Resource

from fileresource import FileResourceFactory, ImageResourceFactory
from pagetemplateresource import PageTemplateResourceFactory
from resources import empty

_marker = object()

# we only need this class as a context for DirectoryResource
class Directory(object):

def __init__(self, path, checker, name):
self.path = path
self.checker = checker
self.__name__ = name

class DirectoryResource(BrowserView, Resource):

implements(IBrowserPublisher)

resource_factories = {
'.gif': ImageResourceFactory,
'.png': ImageResourceFactory,
'.jpg': ImageResourceFactory,
'.pt': PageTemplateResourceFactory,
'.zpt': PageTemplateResourceFactory,
'.html': PageTemplateResourceFactory,
}

default_factory = FileResourceFactory

def publishTraverse(self, request, name):
'''See interface IBrowserPublisher'''
return self.get(name)

def browserDefault(self, request):
'''See interface IBrowserPublisher'''
return empty, ()

def __getitem__(self, name):
res = self.get(name, None)
if res is None:
raise KeyError(name)
return res

def get(self, name, default=_marker):
path = self.context.path
filename = os.path.join(path, name)
isfile = os.path.isfile(filename)
isdir = os.path.isdir(filename)

if not (isfile or isdir):
if default is _marker:
raise NotFound(None, name)
return default

if isfile:
ext = os.path.splitext(os.path.normcase(name))[1]
factory = self.resource_factories.get(ext, self.default_factory)
else:
factory = DirectoryResourceFactory

rname = posixpath.join(self.__name__, name)
resource = factory(filename, self.context.checker, rname)(self.request)
resource.__parent__ = self
return resource

class DirectoryResourceFactory(object):

def __init__(self, path, checker, name):
self.__dir = Directory(path, checker, name)
self.__checker = checker
self.__name = name

def __call__(self, request):
resource = DirectoryResource(self.__dir, request)
resource.__Security_checker__ = self.__checker
resource.__name__ = self.__name
return resource
2 changes: 1 addition & 1 deletion browser/fileresource.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
from zope.datetime import time as timeFromDateTimeString
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.publisher.browser import BrowserView

from zope.app.publisher.browser import BrowserView
from zope.app.publisher.fileresource import File, Image
from zope.app.publisher.browser.resource import Resource

Expand Down
46 changes: 46 additions & 0 deletions browser/managementviewselector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Selecting first available and allowed management view
$Id$
"""
from zope.interface import implements
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.publisher.browser import BrowserView
from zope.app.publisher.browser.menu import getFirstMenuItem

class ManagementViewSelector(BrowserView):
"""View that selects the first available management view.
Support 'zmi_views' actions like: 'javascript:alert("hello")',
'../view_on_parent.html' or '++rollover++'.
"""
implements(IBrowserPublisher)

def browserDefault(self, request):
return self, ()

def __call__(self):
item = getFirstMenuItem('zmi_views', self.context, self.request)

if item:
redirect_url = item['action']
if not (redirect_url.startswith('../') or \
redirect_url.lower().startswith('javascript:') or \
redirect_url.lower().startswith('++')):
self.request.response.redirect(redirect_url)
return u''

self.request.response.redirect('.') # Redirect to content/
return u''
192 changes: 192 additions & 0 deletions browser/menu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Menu Registration code.
$Id$
"""
__docformat__ = "reStructuredText"
import sys

import zope.component
from zope.interface import Interface, implements, providedBy
from zope.security import checkPermission, canAccess
from zope.security.interfaces import Unauthorized, Forbidden
from zope.security.proxy import removeSecurityProxy
from zope.publisher.browser import BrowserView

from zope.app.pagetemplate.engine import Engine
from zope.app.publication.browser import PublicationTraverser
from zope.app.publisher.interfaces.browser import IMenuAccessView
from zope.app.publisher.interfaces.browser import IBrowserMenu
from zope.app.publisher.interfaces.browser import IBrowserMenuItem
from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
from zope.app.publisher.interfaces.browser import IMenuItemType

class BrowserMenu(object):
"""Browser Menu"""
implements(IBrowserMenu)

def __init__(self, id, title=u'', description=u''):
self.id = id
self.title = title
self.description = description

def getMenuItemType(self):
return zope.component.getUtility(IMenuItemType, self.id)

def getMenuItems(self, object, request):
"""Return menu item entries in a TAL-friendly form."""
result = []
for name, item in zope.component.getAdapters((object, request),
self.getMenuItemType()):
if item.available():
result.append(item)

# Now order the result. This is not as easy as it seems.
#
# (1) Look at the interfaces and put the more specific menu entries
# to the front.
# (2) Sort unabigious entries by order and then by title.
ifaces = list(providedBy(removeSecurityProxy(object)).__iro__)
result = [(ifaces.index(item._for or Interface),
item.order, item.title, item) for item in result]
result.sort()

result = [
{'title': item.title,
'description': item.description,
'action': item.action,
'selected': (item.selected() and u'selected') or u'',
'icon': item.icon,
'extra': item.extra,
'submenu': (IBrowserSubMenuItem.providedBy(item) and
getMenu(item.submenuId, object, request)) or None}
for index, order, title, item in result]

return result


class BrowserMenuItem(BrowserView):
"""Browser Menu Item Class"""
implements(IBrowserMenuItem)

# See zope.app.publisher.interfaces.browser.IBrowserMenuItem
title = u''
description = u''
action = u''
extra = None
order = 0
permission = None
filter = None
icon = None
_for = Interface

def available(self):
"""See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
# Make sure we have the permission needed to access the menu's action
if self.permission is not None:
# If we have an explicit permission, check that we
# can access it.
if not checkPermission(self.permission, self.context):
return False

elif self.action != u'':
# Otherwise, test access by attempting access
path = self.action
l = self.action.find('?')
if l >= 0:
path = self.action[:l]

traverser = PublicationTraverser()
try:
view = traverser.traverseRelativeURL(
self.request, self.context, path)
except (Unauthorized, Forbidden, LookupError):
return False
else:
# we're assuming that view pages are callable
# this is a pretty sound assumption
if not canAccess(view, '__call__'):
return False

# Make sure that we really want to see this menu item
if self.filter is not None:

try:
include = self.filter(Engine.getContext(
context = self.context,
nothing = None,
request = self.request,
modules = sys.modules,
))
except Unauthorized:
return False
else:
if not include:
return False

return True

def selected(self):
"""See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
request_url = self.request.getURL()

normalized_action = self.action
if self.action.startswith('@@'):
normalized_action = self.action[2:]

if request_url.endswith('/'+normalized_action):
return True
if request_url.endswith('/++view++'+normalized_action):
return True
if request_url.endswith('/@@'+normalized_action):
return True

return False


class BrowserSubMenuItem(BrowserMenuItem):
"""Browser Menu Item Base Class"""
implements(IBrowserSubMenuItem)

# See zope.app.publisher.interfaces.browser.IBrowserSubMenuItem
submenuId = None

def selected(self):
"""See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
if self.action is u'':
return False
return super(BrowserSubMenuItem, self).selected()


def getMenu(id, object, request):
"""Return menu item entries in a TAL-friendly form."""
menu = zope.component.getUtility(IBrowserMenu, id)
return menu.getMenuItems(object, request)


def getFirstMenuItem(id, object, request):
"""Get the first item of a menu."""
items = getMenu(id, object, request)
if items:
return items[0]
return None


class MenuAccessView(BrowserView):
"""A view allowing easy access to menus."""
implements(IMenuAccessView)

def __getitem__(self, menuId):
return getMenu(menuId, self.context, self.request)

0 comments on commit 3d5e100

Please sign in to comment.