Back to index

plone3  3.1.7
kssview.py
Go to the documentation of this file.
00001 # Copyright (c) 2005-2007
00002 # Authors: KSS Project Contributors (see docs/CREDITS.txt)
00003 #
00004 # This program is free software; you can redistribute it and/or modify
00005 # it under the terms of the GNU General Public License version 2 as published
00006 # by the Free Software Foundation.
00007 #
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 #
00013 # You should have received a copy of the GNU General Public License
00014 # along with this program; if not, write to the Free Software
00015 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00016 # 02111-1307, USA.
00017 
00018 '''\
00019 KSS Base view class
00020 
00021 All the implementations should create a specialization
00022 of this class when building their browser views.
00023 
00024 The policy is that a method should build up a command
00025 set on available methods and then return self.render().
00026 
00027 The default command set is implemented in the base class
00028 as well.
00029 '''
00030 
00031 import warnings
00032 
00033 try:
00034     from Products.Five import BrowserView
00035 except ImportError:
00036     from zope.publisher.browser import BrowserView
00037 
00038 from kss.core.commands import KSSCommands
00039 from kss.core.interfaces import IKSSView, ICommandSet
00040 from kss.core.pluginregistry.commandset import getRegisteredCommandSet
00041 
00042 from zope import component, interface, event
00043 from zope.interface.adapter import VerifyingAdapterRegistry
00044 from zope.component.globalregistry import BaseGlobalComponents
00045 from zope.component.interfaces import IObjectEvent
00046 from zope.app.component.interfaces import ISite
00047 from zope.app.publication.zopepublication import BeforeTraverseEvent
00048 
00049 HAS_FIVE_LSM = True
00050 try:
00051     from five.localsitemanager import registry
00052     from zope.component.registry import UtilityRegistration
00053 except ImportError:
00054     HAS_FIVE_LSM = False
00055 
00056 
00057 class SiteViewComponents(BaseGlobalComponents):
00058 
00059     def _init_registries(self):
00060         # This is why this class is needed: we can't work with a
00061         # regular AdapterRegistry because it wants to do funny things
00062         # with __bases__.
00063         self.adapters = VerifyingAdapterRegistry()
00064         self.utilities = VerifyingAdapterRegistry()
00065         if HAS_FIVE_LSM:
00066             self.utilities.LookupClass = registry.FiveVerifyingAdapterLookup
00067             self.utilities._createLookup()
00068             self.utilities.__parent__ = self
00069 
00070     if HAS_FIVE_LSM:
00071         def registeredUtilities(self):
00072             for ((provided, name), (component, info)
00073                  ) in self._utility_registrations.iteritems():
00074                 yield UtilityRegistration(self, provided, name,
00075                                           registry._wrap(component, self),
00076                                           info)
00077 
00078 class SiteView(BrowserView):
00079     """A browser view that is its own site
00080     """
00081     interface.implements(ISite)
00082 
00083     def __init__(self, context, request):
00084         super(SiteView, self).__init__(context, request)
00085 
00086         next = component.getSiteManager()
00087         self._sitemanager = SiteViewComponents('siteview')
00088         self._sitemanager.__bases__ = (next, )
00089         if HAS_FIVE_LSM:
00090             self._sitemanager.__parent__ = self
00091 
00092         # On Five, we should wrap it in the acquisition context
00093         # see, if self has aq_parent, it is done obligatoraly
00094         try:
00095             self.context.aq_parent
00096         except AttributeError:
00097             # Zope3 - No problem.
00098             wrapped_view = self
00099         else:
00100             wrapped_view = self.__of__(self.context)
00101 
00102         # register object event handler
00103         self._sitemanager.registerHandler(wrapped_view._eventRedispatcher)
00104 
00105     # Zope 2.10 doesn't send BeforeTraverseEvents for all objects,
00106     # only the ones for which you explicitly enable a before traverse
00107     # hook available from Five.component.  Hence, this view won't
00108     # become the current site when it's traversed.  This is bad,
00109     # hopefully Zope 2.11 will fix this.  For now, we'll just take
00110     # care of it ourselves...
00111     def __before_publishing_traverse__(self, obj, request):
00112         event.notify(BeforeTraverseEvent(self, request))
00113 
00114     # ISite interface
00115 
00116     def getSiteManager(self):
00117         return self._sitemanager
00118 
00119     def setSiteManager(self, sm):
00120         raise TypeError("Site manager of SiteView can't be changed.")
00121 
00122     @component.adapter(IObjectEvent)
00123     def _eventRedispatcher(self, event):
00124         """This works similar to zope.component.event.objectEventNotify:
00125         It dispatches object events to subscribers that listen to
00126         (object, view, event)."""
00127         adapters = component.subscribers((event.object, self, event), None)
00128         for adapter in adapters:
00129             pass # getting them does the work
00130 
00131 class KSSView(SiteView):
00132     """KSS view
00133 
00134     This allows setting up the content of the response, and then
00135     generate it out.
00136     """
00137     interface.implements(IKSSView)
00138 
00139     def __init__(self, context, request):
00140         super(KSSView, self).__init__(context, request)
00141         self._initcommands()
00142 
00143     def _initcommands(self):
00144         self.commands = KSSCommands()
00145 
00146     # XXX avoid weird acquisition behaviour in Zope 2... this should
00147     # go away when Five views aren't Acquisition objects anymore.
00148     def _set_context(self, context):
00149         self._context = [context]
00150     def _get_context(self):
00151         return self._context[0]
00152     context = property(_get_context, _set_context)
00153 
00154     def render(self):
00155         """Views can use this to return their command set."""
00156         return self.commands.render(self.request)
00157 
00158     def cancelRedirect(self):
00159         if self.request.response.getStatus() in (302, 303):
00160             # Try to not redirect if requested
00161             self.request.response.setStatus(200)
00162 
00163     def getCommands(self):
00164         return self.commands
00165 
00166     def getCommandSet(self, name):
00167         commandset = getRegisteredCommandSet(name)
00168         # return the adapted view
00169         return commandset.provides(self)
00170 
00171 class CommandSet:
00172     interface.implements(ICommandSet)
00173 
00174     def __init__(self, view):
00175         self.view = view
00176         self.context = self.view.context
00177         self.request = self.view.request
00178         self.commands =  self.view.commands
00179 
00180     def getCommandSet(self, name):
00181         return self.view.getCommandSet(name)
00182 
00183 # BBB deprecated
00184 class AzaxBaseView(KSSView):
00185     def __init__(self, *args, **kw):
00186         message = "'AzaxBaseView' is deprecated," \
00187             "use 'KSSView' instead."
00188         warnings.warn(message, DeprecationWarning, 2)
00189         KSSView.__init__(self, *args, **kw)
00190 
00191 class AzaxViewAdapter(CommandSet):
00192     def __init__(self, *args, **kw):
00193         message = "'AzaxViewAdapter' is deprecated," \
00194             "use 'CommandSet' instead."
00195         warnings.warn(message, DeprecationWarning, 2)
00196         CommandSet.__init__(self, *args, **kw)
00197