Back to index

plone3  3.1.7
zpt.py
Go to the documentation of this file.
00001 from zope.component import adapter, getSiteManager
00002 from zope.viewlet.viewlet import ViewletBase
00003 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
00004 from zope.app.container.interfaces import IObjectRemovedEvent
00005 from zope.viewlet.interfaces import IViewlet, IViewletManager
00006 from zope.interface import implements
00007 
00008 from five.customerize.interfaces import ITTWViewTemplate
00009 from five.customerize.utils import checkPermission
00010 from plone.portlets.interfaces import IPortletRenderer
00011 from plone.portlets.interfaces import IPortletManager
00012 
00013 
00014 class TTWViewTemplate(ZopePageTemplate):
00015     """A template class used to generate Zope 3 views TTW"""
00016     implements(ITTWViewTemplate)
00017 
00018     manage_options = (
00019         ZopePageTemplate.manage_options[0],
00020         dict(label='Registrations', action='registrations.html'),
00021         ) + ZopePageTemplate.manage_options[2:]
00022 
00023     def __init__(self, id, text=None, content_type='text/html', strict=True,
00024                  encoding='utf-8', view=None, permission=None, name=None):
00025         self.view = view
00026         self.permission = permission
00027         self.name = name
00028         super(TTWViewTemplate, self).__init__(id, text, content_type, encoding,
00029                                               strict)
00030 
00031     def __call__(self, context, request, viewlet=None, manager=None, data=None):
00032         #XXX raise a sensible exception if context and request are
00033         # omitted, IOW, if someone tries to render the template not as
00034         # a view.
00035 
00036         # the security check is now deferred until the template/viewlet/portlet
00037         # is actually called, because it may be looked up during traversal,
00038         # in which case there's no proper security context yet
00039         if IPortletManager.providedBy(manager):
00040             return TTWPortletRenderer(context, request, self, self.view,
00041                 manager, data, self.permission)
00042         if IViewletManager.providedBy(manager):
00043             return TTWViewletRenderer(context, request, self, self.view,
00044                 viewlet, manager, self.permission)
00045         else:
00046             return TTWViewTemplateRenderer(context, request, self, self.view, self.permission)
00047 
00048     # overwrite Shared.DC.Scripts.Binding.Binding's before traversal
00049     # hook that would prevent to look up views for instances of this
00050     # class.
00051     def __before_publishing_traverse__(self, self2, request):
00052         pass
00053 
00054 
00055 class TTWViewTemplateRenderer(object):
00056     """The view object for the TTW View Template.
00057 
00058     When a TTWViewTemplate-based view is looked up, an object of this
00059     class is instantiated.  It holds a reference to the
00060     TTWViewTemplate object which it will use in the render process
00061     (__call__).
00062     """
00063 
00064     def __init__(self, context, request, template, view, permission=None):
00065         self.context = context
00066         self.request = request
00067         self.template = template
00068         self.view = view
00069         self.permission = permission
00070 
00071     def __call__(self, *args, **kwargs):
00072         """Render the TTWViewTemplate-based view.
00073         """
00074         view = self._getView()
00075         # we need to override the template's context and request as
00076         # they generally point to the wrong objects (a template's
00077         # context usually is what it was acquired from, which isn't
00078         # what the context is for a view template).
00079         bound_names = {'context': self.context,
00080                        'request': self.request,
00081                        'view': view}
00082         template = self.template.__of__(self.context)
00083         return template._exec(bound_names, args, kwargs)
00084 
00085     def _getView(self):
00086         checkPermission(self.permission, self.context)
00087         view = self.view
00088         if view is not None:
00089             # Filesystem-based view templates are trusted code and
00090             # have unrestricted access to the view class.  We simulate
00091             # that for TTW templates (which are trusted code) by
00092             # creating a subclass with unrestricted access to all
00093             # subobjects.
00094             class TTWView(view):
00095                 __allow_access_to_unprotected_subobjects__ = 1
00096             view = TTWView(self.context, self.request)
00097         return view
00098 
00099     # Zope 2 wants to acquisition-wrap every view object (via __of__).
00100     # We don't need this as the TTWViewTemplate object is already
00101     # properly acquisition-wrapped in __call__.  Nevertheless we need
00102     # to support the __of__ method as a no-op.
00103     def __of__(self, obj):
00104         return self
00105 
00106 
00107 class TTWViewletRenderer(object):
00108     """ analogon to TTWViewTemplateRenderer for viewlets """
00109     implements(IViewlet)
00110 
00111     __allow_access_to_unprotected_subobjects__ = True
00112 
00113     def __init__(self, context, request, template, view, viewlet=None, manager=None, permission=None):
00114         self.context = context
00115         self.request = request
00116         self.template = template
00117         self.view = view
00118         self.viewlet = viewlet
00119         self.manager = manager
00120         self.ttwviewlet = None
00121         self.permission = permission
00122 
00123     def update(self):
00124         """ update the viewlet before `render` is called """
00125         view = self._getViewlet().update()
00126 
00127     def render(self, *args, **kwargs):
00128         """ render the viewlet using the customized template """
00129         view = self._getViewlet()
00130         # we need to override the template's context and request as
00131         # they generally point to the wrong objects (a template's
00132         # context usually is what it was acquired from, which isn't
00133         # what the context is for a view template).
00134         bound_names = {'context': self.context,
00135                        'request': self.request,
00136                        'view': view}
00137         template = self.template.__of__(self.context)
00138         return template._exec(bound_names, args, kwargs)
00139 
00140     def _getViewlet(self):
00141         checkPermission(self.permission, self.context)
00142         if self.ttwviewlet is not None:
00143             return self.ttwviewlet
00144         view = self.view
00145         if view is not None:
00146             # Filesystem-based view templates are trusted code and
00147             # have unrestricted access to the view class.  We simulate
00148             # that for TTW templates (which are trusted code) by
00149             # creating a subclass with unrestricted access to all
00150             # subobjects.
00151             class TTWViewlet(view, ViewletBase):
00152                 __allow_access_to_unprotected_subobjects__ = 1
00153             view = TTWViewlet(self.context, self.request, self.viewlet, self.manager)
00154         self.ttwviewlet = view
00155         return view
00156 
00157     # Zope 2 wants to acquisition-wrap every view object (via __of__).
00158     # We don't need this as the TTWViewTemplate object is already
00159     # properly acquisition-wrapped in __call__.  Nevertheless we need
00160     # to support the __of__ method as a no-op.
00161     def __of__(self, obj):
00162         return self
00163 
00164 
00165 class TTWPortletRenderer(object):
00166     """ analogon to TTWViewletRenderer for portlets """
00167     implements(IPortletRenderer)
00168 
00169     __allow_access_to_unprotected_subobjects__ = True
00170 
00171     def __init__(self, context, request, template, view, manager=None, data=None, permission=None):
00172         self.context = context
00173         self.request = request
00174         self.template = template
00175         self.view = view
00176         self.manager = manager
00177         self.data = data
00178         self.renderer = None
00179         self.permission = permission
00180 
00181     def update(self):
00182         """ update the portlet before `render` is called """
00183         view = self._getRenderer().update()
00184 
00185     def render(self, *args, **kwargs):
00186         """ render the portlet using the customized template """
00187         view = self._getRenderer()
00188         # we need to override the template's context and request as
00189         # they generally point to the wrong objects (a template's
00190         # context usually is what it was acquired from, which isn't
00191         # what the context is for a view template).
00192         bound_names = {'context': self.context,
00193                        'request': self.request,
00194                        'view': view}
00195         template = self.template.__of__(self.context)
00196         return template._exec(bound_names, args, kwargs)
00197 
00198     def _getRenderer(self):
00199         checkPermission(self.permission, self.context)
00200         if self.renderer is not None:
00201             return self.renderer
00202         view = self.view
00203         if view is not None:
00204             # Filesystem-based view templates are trusted code and
00205             # have unrestricted access to the view class.  We simulate
00206             # that for TTW templates (which are trusted code) by
00207             # creating a subclass with unrestricted access to all
00208             # subobjects.
00209             class TTWPortlet(view):
00210                 __allow_access_to_unprotected_subobjects__ = 1
00211             view = TTWPortlet(self.context, self.request, self.view, self.manager, self.data)
00212         self.renderer = view
00213         return view
00214 
00215     @property
00216     def available(self):
00217         return self._getRenderer().available
00218 
00219     # Zope 2 wants to acquisition-wrap every view object (via __of__).
00220     # We don't need this as the TTWViewTemplate object is already
00221     # properly acquisition-wrapped in __call__.  Nevertheless we need
00222     # to support the __of__ method as a no-op.
00223     def __of__(self, obj):
00224         return self
00225 
00226 
00227 @adapter(TTWViewTemplate, IObjectRemovedEvent)
00228 def unregisterViewWhenZPTIsDeleted(zpt, event):
00229     components = getSiteManager(zpt)
00230     for reg in components.registeredAdapters():
00231         if reg.factory == zpt:
00232             components.unregisterAdapter(reg.factory, reg.required,
00233                                          reg.provided, reg.name)
00234             break
00235