--- a/src/pyams_portal/portlet.py Thu Oct 08 12:26:42 2015 +0200
+++ b/src/pyams_portal/portlet.py Mon Jan 18 18:09:46 2016 +0100
@@ -20,97 +20,42 @@
import venusian
# import interfaces
-from pyams_portal.interfaces import IPortlet, IPortletRenderer, IPortletConfiguration, \
- IPortalPage, IPortletPreviewer
+from pyams_portal.interfaces import IPortlet, IPortletSettings, IPortletConfiguration, IPortletPreviewer, \
+ IPortletRenderer, IPortalPortletsConfiguration, IPortalTemplate, IPortalContext, IPortalPage
from zope.schema.interfaces import IVocabularyFactory
+from zope.traversing.interfaces import ITraversable
# import packages
from persistent import Persistent
+from persistent.mapping import PersistentMapping
+from pyams_utils.adapter import adapter_config, ContextAdapter
from pyams_utils.request import check_request
from pyams_viewlet.viewlet import ContentProvider
from pyramid.exceptions import ConfigurationError
+from pyramid.threadlocal import get_current_registry
from zope.container.contained import Contained
+from zope.copy import clone
from zope.interface import implementer, provider
+from zope.lifecycleevent import ObjectCreatedEvent
+from zope.location import locate
from zope.schema.fieldproperty import FieldProperty
-from zope.schema.vocabulary import getVocabularyRegistry, SimpleVocabulary, SimpleTerm
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm, getVocabularyRegistry
-@implementer(IPortletConfiguration)
-class PortletConfiguration(Persistent, Contained):
- """Portlet configuration"""
-
- template = None
- portlet_name = None
- slot_name = FieldProperty(IPortletConfiguration['slot_name'])
- position = FieldProperty(IPortletConfiguration['position'])
- visible = FieldProperty(IPortletConfiguration['visible'])
- _inherit_parent = FieldProperty(IPortletConfiguration['inherit_parent'])
-
- def __init__(self, portlet):
- self.portlet_name = portlet.name
-
- @property
- def can_inherit(self):
- return IPortalPage.providedBy(self.__parent__)
-
- @property
- def inherit_parent(self):
- return self._inherit_parent if self.can_inherit else False
-
- @inherit_parent.setter
- def inherit_parent(self, value):
- self._inherit_parent = value
-
+#
+# Portlets utilities
+#
@implementer(IPortlet)
class Portlet(object):
- """Base portlet content provider"""
+ """Base portlet utility"""
permission = FieldProperty(IPortlet['permission'])
toolbar_image = None
toolbar_css_class = 'fa fa-fw fa-2x fa-edit'
-
-@provider(IVocabularyFactory)
-class PortletVocabulary(SimpleVocabulary):
- """Portlet vocabulary"""
-
- def __init__(self, context):
- request = check_request()
- translate = request.localizer.translate
- utils = request.registry.getUtilitiesFor(IPortlet)
- terms = [SimpleTerm(name, title=translate(util.label))
- for name, util in sorted(utils, key=lambda x: translate(x[1].label))]
- super(PortletVocabulary, self).__init__(terms)
-
-getVocabularyRegistry().register('PyAMS portal portlets', PortletVocabulary)
-
-
-class PortletContentProvider(ContentProvider):
- """Bae portlet content provider"""
-
- def __init__(self, context, request, view, portlet_config):
- super(PortletContentProvider, self).__init__(context, request, view)
- self.__parent__ = view
- self.configuration = portlet_config
- self.portlet = self.request.registry.getUtility(IPortlet, name=portlet_config.portlet_name)
-
- def __call__(self):
- if self.portlet.permission and not self.request.has_permission(self.portlet.permission):
- return ''
- self.update()
- return self.render()
-
-
-@implementer(IPortletPreviewer)
-class PortletPreviewer(PortletContentProvider):
- """Portlet previewer adapter"""
-
-
-@implementer(IPortletRenderer)
-class PortletRenderer(PortletContentProvider):
- """Portlet renderer adapter"""
+ settings_class = None
class portlet_config(object):
@@ -158,3 +103,176 @@
settings['_info'] = info.codeinfo # fbo "action_method"
return wrapped
+
+
+@provider(IVocabularyFactory)
+class PortletVocabulary(SimpleVocabulary):
+ """Portlet vocabulary"""
+
+ def __init__(self, context):
+ request = check_request()
+ translate = request.localizer.translate
+ utils = request.registry.getUtilitiesFor(IPortlet)
+ terms = [SimpleTerm(name, title=translate(util.label))
+ for name, util in sorted(utils, key=lambda x: translate(x[1].label))]
+ super(PortletVocabulary, self).__init__(terms)
+
+getVocabularyRegistry().register('PyAMS portal portlets', PortletVocabulary)
+
+
+#
+# Portlets renderers
+#
+
+class PortletContentProvider(ContentProvider):
+ """Base portlet content provider"""
+
+ def __init__(self, context, request, view, settings):
+ super(PortletContentProvider, self).__init__(context, request, view)
+ self.__parent__ = view
+ self.settings = settings
+ self.portlet = self.request.registry.getUtility(IPortlet, name=settings.configuration.portlet_name)
+
+ def __call__(self):
+ if self.portlet.permission and not self.request.has_permission(self.portlet.permission):
+ return ''
+ self.update()
+ return self.render()
+
+
+@implementer(IPortletPreviewer)
+class PortletPreviewer(PortletContentProvider):
+ """Portlet previewer adapter"""
+
+
+@implementer(IPortletRenderer)
+class PortletRenderer(PortletContentProvider):
+ """Portlet renderer adapter"""
+
+
+#
+# Portlet configuration
+#
+
+@implementer(IPortletSettings)
+class PortletSettings(Persistent, Contained):
+ """Portlet settings persistent class"""
+
+ visible = FieldProperty(IPortletSettings['visible'])
+
+ __name__ = '++settings++'
+
+ def __init__(self, configuration):
+ self.__parent__ = configuration
+
+ @property
+ def configuration(self):
+ return self.__parent__
+
+
+@implementer(IPortletConfiguration)
+class PortletConfiguration(Persistent, Contained):
+ """Portlet configuration persistent class
+
+ PortletConfiguration.__parent__ points to context where configuration is applied
+ PortletConfiguration.parent points to context from where configuration is inherited
+ """
+
+ portlet_id = FieldProperty(IPortletConfiguration['portlet_id'])
+ portlet_name = None
+ _inherit_parent = FieldProperty(IPortletConfiguration['inherit_parent'])
+ _settings = FieldProperty(IPortletConfiguration['settings'])
+
+ def __init__(self, portlet):
+ self.portlet_name = portlet.name
+ self._settings = portlet.settings_class(self)
+
+ @property
+ def can_inherit(self):
+ return not IPortalTemplate.providedBy(self.__parent__)
+
+ @property
+ def inherit_parent(self):
+ return self._inherit_parent if self.can_inherit else False
+
+ @inherit_parent.setter
+ def inherit_parent(self, value):
+ if (not value) or self.can_inherit:
+ self._inherit_parent = value
+
+ @property
+ def parent(self):
+ parent = self.__parent__
+ if IPortalTemplate.providedBy(parent):
+ return parent
+ while IPortalContext.providedBy(parent):
+ configuration = IPortalPortletsConfiguration(parent).get_portlet_configuration(self.portlet_id)
+ if not configuration.inherit_parent:
+ return parent
+ if not IPortalContext.providedBy(parent.__parent__):
+ break
+ parent = parent.__parent__
+ page = IPortalPage(parent, None)
+ if page is not None:
+ return page.template
+
+ @property
+ def settings(self):
+ if self.inherit_parent:
+ return IPortalPortletsConfiguration(self.parent).get_portlet_configuration(self.portlet_id).settings
+ else:
+ return self._settings
+
+ @property
+ def editor_settings(self):
+ return self._settings
+
+
+@adapter_config(context=IPortlet, provides=IPortletConfiguration)
+def PortletConfigurationAdapter(portlet):
+ """Portlet configuration factory"""
+ return PortletConfiguration(portlet)
+
+
+@adapter_config(context=IPortletConfiguration, provides=IPortletSettings)
+def PortletConfigurationSettingsAdapter(configuration):
+ """Portlet configuration settings adapter"""
+ return configuration.settings
+
+
+@adapter_config(name='settings', context=IPortletConfiguration, provides=ITraversable)
+class PortletConfigurationSettingsTraverser(ContextAdapter):
+ """++settings++ portlet configuration traverser"""
+
+ def traverse(self, name, furtherpath=None):
+ return self.context.settings
+
+
+#
+# Template portlets configuration
+#
+
+@implementer(IPortalPortletsConfiguration)
+class PortalPortletsConfiguration(PersistentMapping, Contained):
+ """Portal portlets configuration"""
+
+ def get_portlet_configuration(self, portlet_id):
+ configuration = self.get(portlet_id)
+ if (configuration is None) and not IPortalTemplate.providedBy(self.__parent__):
+ template = IPortalPage(self.__parent__).template
+ portlets = IPortalPortletsConfiguration(template)
+ configuration = clone(portlets.get_portlet_configuration(portlet_id))
+ get_current_registry().notify(ObjectCreatedEvent(configuration))
+ self.set_portlet_configuration(portlet_id, configuration)
+ return configuration
+
+ def set_portlet_configuration(self, portlet_id, config):
+ config.portlet_id = portlet_id
+ self[portlet_id] = config
+ locate(config, self.__parent__, '++portlet++{0}'.format(portlet_id))
+
+ def delete_portlet_configuration(self, portlet_id):
+ if isinstance(portlet_id, int):
+ portlet_id = (portlet_id,)
+ for p_id in portlet_id:
+ del self[p_id]