src/pyams_portal/portlet.py
changeset 39 f0ef959855e7
parent 34 0a7a5155d352
child 48 afbb9c97d36a
--- a/src/pyams_portal/portlet.py	Wed Jul 12 12:21:40 2017 +0200
+++ b/src/pyams_portal/portlet.py	Wed Jul 12 12:23:32 2017 +0200
@@ -20,9 +20,10 @@
 import venusian
 
 # import interfaces
+from pyams_form.interfaces.form import IFormContextPermissionChecker
 from pyams_portal.interfaces import IPortlet, IPortletSettings, IPortletConfiguration, IPortletPreviewer, \
     IPortletRenderer, IPortalPortletsConfiguration, IPortalTemplate, IPortalContext, IPortalPage, \
-    IPortalTemplateConfiguration
+    IPortalTemplateConfiguration, MANAGE_TEMPLATE_PERMISSION
 from zope.traversing.interfaces import ITraversable
 
 # import packages
@@ -189,7 +190,12 @@
 
 @implementer(IPortletSettings)
 class PortletSettings(Persistent, Contained):
-    """Portlet settings persistent class"""
+    """Portlet settings persistent class
+
+    This class is supposed to be sub-classed by all custom portlet subclasses to
+    store their configuration settings.
+    Each portlet sub-class must define it's settings class in it's "settings_class" attribute.
+    """
 
     visible = FieldProperty(IPortletSettings['visible'])
     _renderer = FieldProperty(IPortletSettings['renderer'])
@@ -228,8 +234,12 @@
 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
+    This class is a generic persistent class which is used to store all portlet
+    configuration and is *not* supposed to be sub-classed.
+
+    PortletConfiguration.__parent__ points to context where configuration is applied (each context or
+    local template).
+    PortletConfiguration.parent points to context from where configuration is inherited.
     """
 
     portlet_id = FieldProperty(IPortletConfiguration['portlet_id'])
@@ -263,7 +273,8 @@
             configuration = IPortalPortletsConfiguration(parent).get_portlet_configuration(self.portlet_id)
             if not configuration.inherit_parent:
                 return parent
-            if not IPortalContext.providedBy(parent.__parent__):
+            page = IPortalPage(parent)
+            if not page.inherit_parent:
                 break
             parent = parent.__parent__
         page = IPortalPage(parent, None)
@@ -302,6 +313,15 @@
         return self.context.settings
 
 
+@adapter_config(context=IPortletConfiguration, provides=IFormContextPermissionChecker)
+class PortletConfigurationPermissionChecker(ContextAdapter):
+    """Portlet configuration permission checker"""
+
+    @property
+    def edit_permission(self):
+        return MANAGE_TEMPLATE_PERMISSION
+
+
 #
 # Template portlets configuration
 #
@@ -310,11 +330,29 @@
 class PortalPortletsConfiguration(PersistentMapping, Contained):
     """Portal portlets configuration"""
 
+    @classmethod
+    def clone(cls, source_config, new_parent):
+        """Clone source configuration"""
+        configuration = source_config.__class__()
+        get_current_registry().notify(ObjectCreatedEvent(configuration))
+        locate(configuration, new_parent)
+        for config_id, config_portlet in source_config.items():
+            config = clone(config_portlet)
+            configuration[config_id] = config
+        return configuration
+
+    def __setitem__(self, key, value):
+        super(PortalPortletsConfiguration, self).__setitem__(key, value)
+        locate(value, self.__parent__, '++portlet++{0}'.format(key))
+
     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)
+        if configuration is None:
+            if IPortalTemplate.providedBy(self.__parent__):
+                portlets = IPortalPortletsConfiguration(self.__parent__)
+            else:
+                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)
@@ -323,7 +361,6 @@
     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):