src/pyams_portal/portlet.py
changeset 266 8a1a1e258f43
parent 263 87994557fc51
child 269 ecbd099f2627
equal deleted inserted replaced
265:69d8c550cc2d 266:8a1a1e258f43
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 import logging
    13 import logging
    14 logger = logging.getLogger('PyAMS (portal)')
       
    15 
    14 
    16 import venusian
    15 import venusian
    17 from persistent import Persistent
    16 from persistent import Persistent
    18 from persistent.mapping import PersistentMapping
    17 from persistent.mapping import PersistentMapping
    19 from pyramid.exceptions import ConfigurationError
    18 from pyramid.exceptions import ConfigurationError
    28 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    27 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    29 from zope.traversing.interfaces import ITraversable
    28 from zope.traversing.interfaces import ITraversable
    30 
    29 
    31 from pyams_cache.beaker import get_cache
    30 from pyams_cache.beaker import get_cache
    32 from pyams_form.interfaces.form import IFormContextPermissionChecker
    31 from pyams_form.interfaces.form import IFormContextPermissionChecker
    33 from pyams_portal.interfaces import IPortalContext, IPortalPage, IPortalPortletsConfiguration, IPortalTemplate, \
    32 from pyams_portal.interfaces import IPortalContext, IPortalPage, IPortalPortletsConfiguration, \
    34     IPortalTemplateConfiguration, IPortlet, IPortletConfiguration, IPortletPreviewer, IPortletRenderer, \
    33     IPortalTemplate, IPortalTemplateConfiguration, IPortlet, IPortletConfiguration, \
    35     IPortletRendererSettings, IPortletSettings, MANAGE_TEMPLATE_PERMISSION, PORTLET_RENDERER_SETTINGS_KEY, PREVIEW_MODE
    34     IPortletPreviewer, IPortletRenderer, IPortletRendererSettings, IPortletSettings, \
    36 from pyams_utils.adapter import ContextAdapter, adapter_config, get_adapter_weight, get_annotation_adapter
    35     MANAGE_TEMPLATE_PERMISSION, PORTLET_RENDERER_SETTINGS_KEY, PREVIEW_MODE
    37 from pyams_utils.factory import get_object_factory, is_interface, factory_config
    36 from pyams_utils.adapter import ContextAdapter, adapter_config, get_adapter_weight, \
       
    37     get_annotation_adapter
       
    38 from pyams_utils.factory import factory_config, get_object_factory, is_interface
    38 from pyams_utils.interfaces import ICacheKeyValue
    39 from pyams_utils.interfaces import ICacheKeyValue
    39 from pyams_utils.interfaces.url import DISPLAY_CONTEXT
    40 from pyams_utils.interfaces.url import DISPLAY_CONTEXT
    40 from pyams_utils.registry import get_global_registry
    41 from pyams_utils.registry import get_global_registry
    41 from pyams_utils.request import check_request
    42 from pyams_utils.request import check_request
    42 from pyams_utils.vocabulary import vocabulary_config
    43 from pyams_utils.vocabulary import vocabulary_config
    43 from pyams_viewlet.viewlet import ViewContentProvider
    44 from pyams_viewlet.viewlet import ViewContentProvider
    44 
    45 
       
    46 
    45 __docformat__ = 'restructuredtext'
    47 __docformat__ = 'restructuredtext'
       
    48 
       
    49 from pyams_portal import _
       
    50 
       
    51 
       
    52 logger = logging.getLogger('PyAMS (portal)')
    46 
    53 
    47 
    54 
    48 #
    55 #
    49 # Portlets utilities
    56 # Portlets utilities
    50 #
    57 #
    88             else:
    95             else:
    89                 factory = None
    96                 factory = None
    90                 component = ob
    97                 component = ob
    91 
    98 
    92             config = context.config.with_package(info.module)
    99             config = context.config.with_package(info.module)
    93             logger.debug("Registering portlet {0} named '{1}'".format(str(component) if component else str(factory),
   100             logger.debug("Registering portlet {0} named '{1}'".format(
    94                                                                       name))
   101                 str(component) if component else str(factory), name))
    95             config.registry.registerUtility(component=component, factory=factory,
   102             config.registry.registerUtility(component=component, factory=factory,
    96                                             provided=IPortlet, name=name)
   103                                             provided=IPortlet, name=name)
    97 
   104 
    98         info = self.venusian.attach(wrapped, callback, category='pyams_portal',
   105         info = self.venusian.attach(wrapped, callback, category='pyams_portal',
    99                                     depth=depth + 1)
   106                                     depth=depth + 1)
   128 class PortletContentProvider(ViewContentProvider):
   135 class PortletContentProvider(ViewContentProvider):
   129     """Base portlet content provider"""
   136     """Base portlet content provider"""
   130 
   137 
   131     def __init__(self, context, request, view, settings):
   138     def __init__(self, context, request, view, settings):
   132         super(PortletContentProvider, self).__init__(context, request, view)
   139         super(PortletContentProvider, self).__init__(context, request, view)
   133         self.portlet = request.registry.queryUtility(IPortlet, name=settings.configuration.portlet_name)
   140         self.portlet = request.registry.queryUtility(IPortlet,
       
   141                                                      name=settings.configuration.portlet_name)
   134         self.settings = settings
   142         self.settings = settings
   135 
   143 
   136     def render(self):
   144     def render(self):
   137         if self.portlet is None:
   145         if self.portlet is None:
   138             return ''
   146             return ''
   139         if self.portlet.permission and not self.request.has_permission(self.portlet.permission):
   147         if self.portlet.permission and not self.request.has_permission(self.portlet.permission):
   140             return ''
   148             return ''
   141         return super(PortletContentProvider, self).render()
   149         return super(PortletContentProvider, self).render()
       
   150 
       
   151 
       
   152 PREVIEW_PREFIX = '''<div class="padding-x-5 text-info">
       
   153     <span>{label}</span>
       
   154     {renderer}
       
   155 </div>'''
   142 
   156 
   143 
   157 
   144 @implementer(IPortletPreviewer)
   158 @implementer(IPortletPreviewer)
   145 class PortletPreviewer(PortletContentProvider):
   159 class PortletPreviewer(PortletContentProvider):
   146     """Portlet previewer adapter"""
   160     """Portlet previewer adapter"""
   157 
   171 
   158     def render(self):
   172     def render(self):
   159         if self.settings.renderer == 'hidden':
   173         if self.settings.renderer == 'hidden':
   160             return render('templates/portlet-hidden.pt', {}, request=self.request)
   174             return render('templates/portlet-hidden.pt', {}, request=self.request)
   161         else:
   175         else:
   162             return super(PortletPreviewer, self).render()
   176             result = super(PortletPreviewer, self).render()
       
   177             settings = self.settings
       
   178             if settings.renderer:
       
   179                 renderer = settings.get_renderer()
       
   180                 translate = self.request.localizer.translate
       
   181                 result = PREVIEW_PREFIX.format(label=translate(_("Renderer:")),
       
   182                                                renderer=translate(renderer.label)) + result
       
   183             return result
   163 
   184 
   164 
   185 
   165 PORTLETS_CACHE_REGION = 'portlets'
   186 PORTLETS_CACHE_REGION = 'portlets'
   166 PORTLETS_CACHE_NAME = 'PyAMS::portlet'
   187 PORTLETS_CACHE_NAME = 'PyAMS::portlet'
   167 
   188 
   208                                              lang=self.request.locale_name)
   229                                              lang=self.request.locale_name)
   209         else:
   230         else:
   210             return PORTLETS_CACHE_DISPLAY_CONTEXT_KEY.format(portlet=ICacheKeyValue(self.settings),
   231             return PORTLETS_CACHE_DISPLAY_CONTEXT_KEY.format(portlet=ICacheKeyValue(self.settings),
   211                                                              hostname=self.request.host,
   232                                                              hostname=self.request.host,
   212                                                              context=ICacheKeyValue(self.context),
   233                                                              context=ICacheKeyValue(self.context),
   213                                                              display=ICacheKeyValue(display_context),
   234                                                              display=ICacheKeyValue(
       
   235                                                                  display_context),
   214                                                              lang=self.request.locale_name)
   236                                                              lang=self.request.locale_name)
   215 
   237 
   216     def render(self):
   238     def render(self):
   217         preview_mode = self.request.annotations.get(PREVIEW_MODE, False)
   239         preview_mode = self.request.annotations.get(PREVIEW_MODE, False)
   218         if preview_mode or not self.use_portlets_cache:
   240         if preview_mode or not self.use_portlets_cache:
   240 
   262 
   241     def __init__(self, context):
   263     def __init__(self, context):
   242         request = check_request()
   264         request = check_request()
   243         translate = request.localizer.translate
   265         translate = request.localizer.translate
   244         terms = [SimpleTerm(name, title=translate(adapter.label))
   266         terms = [SimpleTerm(name, title=translate(adapter.label))
   245                  for name, adapter in sorted(request.registry.getAdapters((request.root, request, request, context),
   267                  for name, adapter in sorted(request.registry.getAdapters((request.root, request,
       
   268                                                                            request, context),
   246                                                                           IPortletRenderer),
   269                                                                           IPortletRenderer),
   247                                              key=get_adapter_weight)]
   270                                              key=get_adapter_weight)]
   248         super(PortletRenderersVocabulary, self).__init__(terms)
   271         super(PortletRenderersVocabulary, self).__init__(terms)
   249 
   272 
   250 
   273 
   283     def renderer(self, value):
   306     def renderer(self, value):
   284         value = value or ''
   307         value = value or ''
   285         if value == self._renderer:
   308         if value == self._renderer:
   286             return
   309             return
   287         request = check_request()
   310         request = check_request()
   288         renderer = request.registry.queryMultiAdapter((request.root, request, request, self), IPortletRenderer,
   311         renderer = request.registry.queryMultiAdapter((request.root, request, request, self),
   289                                                       name=self._renderer)
   312                                                       IPortletRenderer, name=self._renderer)
   290         if (renderer is not None) and (renderer.target_interface is not None):
   313         if (renderer is not None) and (renderer.target_interface is not None):
   291             noLongerProvides(self, renderer.target_interface)
   314             noLongerProvides(self, renderer.target_interface)
   292         self._renderer = value
   315         self._renderer = value
   293         renderer = request.registry.queryMultiAdapter((request.root, request, request, self), IPortletRenderer,
   316         renderer = request.registry.queryMultiAdapter((request.root, request, request, self),
   294                                                       name=self._renderer)
   317                                                       IPortletRenderer, name=self._renderer)
   295         if (renderer is not None) and (renderer.target_interface is not None):
   318         if (renderer is not None) and (renderer.target_interface is not None):
   296             alsoProvides(self, renderer.target_interface)
   319             alsoProvides(self, renderer.target_interface)
   297 
   320 
   298     def get_renderer(self, request=None):
   321     def get_renderer(self, request=None):
   299         if request is None:
   322         if request is None:
   300             request = check_request()
   323             request = check_request()
   301         return request.registry.queryMultiAdapter((request.root, request, request, self), IPortletRenderer,
   324         return request.registry.queryMultiAdapter((request.root, request, request, self),
   302                                                   name=self._renderer)
   325                                                   IPortletRenderer, name=self._renderer)
   303 
   326 
   304     @property
   327     @property
   305     def configuration(self):
   328     def configuration(self):
   306         return self.__parent__
   329         return self.__parent__
   307 
   330 
   383         parent = self.__parent__
   406         parent = self.__parent__
   384         if IPortalTemplate.providedBy(parent):
   407         if IPortalTemplate.providedBy(parent):
   385             return parent
   408             return parent
   386         while True:
   409         while True:
   387             if IPortalContext.providedBy(parent):
   410             if IPortalContext.providedBy(parent):
   388                 configuration = IPortalPortletsConfiguration(parent).get_portlet_configuration(self.portlet_id)
   411                 configuration = IPortalPortletsConfiguration(parent).get_portlet_configuration(
       
   412                     self.portlet_id)
   389                 if not configuration.inherit_parent:
   413                 if not configuration.inherit_parent:
   390                     return parent
   414                     return parent
   391                 page = IPortalPage(parent)
   415                 page = IPortalPage(parent)
   392                 if not page.inherit_parent:
   416                 if not page.inherit_parent:
   393                     break
   417                     break
   399             return page.template
   423             return page.template
   400 
   424 
   401     @property
   425     @property
   402     def settings(self):
   426     def settings(self):
   403         if self.inherit_parent:
   427         if self.inherit_parent:
   404             return IPortalPortletsConfiguration(self.parent).get_portlet_configuration(self.portlet_id).settings
   428             return IPortalPortletsConfiguration(self.parent).get_portlet_configuration(
       
   429                 self.portlet_id).settings
   405         else:
   430         else:
   406             return self._settings
   431             return self._settings
   407 
   432 
   408     @property
   433     @property
   409     def editor_settings(self):
   434     def editor_settings(self):