diff -r 25cf058f7e1d -r 0dd5876f9d70 src/pyams_skin/configuration.py --- a/src/pyams_skin/configuration.py Wed Oct 07 17:52:40 2015 +0200 +++ b/src/pyams_skin/configuration.py Wed Oct 07 17:53:40 2015 +0200 @@ -18,8 +18,9 @@ # import interfaces from pyams_skin.interfaces.configuration import IStaticConfiguration, IConfiguration, \ - SKIN_CONFIGURATION_KEY -from pyams_utils.interfaces.site import IStaticConfigurationManager, IConfigurationManager, IConfigurationFactory + SKIN_CONFIGURATION_KEY, IBackOfficeConfiguration, SKIN_BACK_CONFIGURATION_KEY +from pyams_utils.interfaces.site import IStaticConfigurationManager, IConfigurationManager, IConfigurationFactory, \ + IBackOfficeConfigurationFactory from pyams_utils.interfaces.tales import ITALESExtension from zope.annotation.interfaces import IAnnotations from zope.traversing.interfaces import ITraversable @@ -41,6 +42,10 @@ from pyams_skin import _ +# +# Static configuration +# + @adapter_config(context=(IStaticConfigurationManager, Interface, Interface), provides=IStaticConfiguration) class StaticConfiguration(object): """Default static configuration""" @@ -89,6 +94,11 @@ return registry.queryMultiAdapter((target, self.request, self.view), IStaticConfiguration) +# +# Dynamic front-office configuration +# May be overriden by custom applications +# + @implementer(IConfiguration) class Configuration(Persistent, Contained): """Manageable configuration""" @@ -107,10 +117,9 @@ configuration = annotations.get(SKIN_CONFIGURATION_KEY) if configuration is None: registry = check_request().registry - factory = registry.queryAdapter(context, IConfigurationFactory) - if factory is not None: - configuration = annotations[SKIN_CONFIGURATION_KEY] = factory() - locate(configuration, context, '++configuration++') + factory = registry.queryAdapter(context, IConfigurationFactory, default=Configuration) + configuration = annotations[SKIN_CONFIGURATION_KEY] = factory() + locate(configuration, context, '++configuration++') return configuration @@ -142,3 +151,63 @@ request.context = configuration.icon return MediaFileView(request) return HTTPNotFound() + + +# +# Dynamic back-office configuration +# May be overriden by custom applications +# + +@implementer(IBackOfficeConfiguration) +class BackOfficeConfiguration(Persistent, Contained): + """Back-office manageable configuration""" + + title = FieldProperty(IBackOfficeConfiguration['title']) + login_header = FieldProperty(IBackOfficeConfiguration['login_header']) + login_footer = FieldProperty(IBackOfficeConfiguration['login_footer']) + icon = FileProperty(IBackOfficeConfiguration['icon']) + logo = FileProperty(IBackOfficeConfiguration['logo']) + display_content_icon = FieldProperty(IBackOfficeConfiguration['display_content_icon']) + + +@adapter_config(context=IConfigurationManager, provides=IBackOfficeConfiguration) +def BackOfficeConfigurationFactory(context): + """Back-office configuration factory""" + annotations = IAnnotations(context) + configuration = annotations.get(SKIN_BACK_CONFIGURATION_KEY) + if configuration is None: + registry = check_request().registry + factory = registry.queryAdapter(context, IBackOfficeConfigurationFactory, default=BackOfficeConfiguration) + configuration = annotations[SKIN_BACK_CONFIGURATION_KEY] = factory() + locate(configuration, context, '++back-configuration++') + return configuration + + +@adapter_config(name='back_configuration', context=(Interface, Interface, Interface), provides=ITALESExtension) +class BackOfficeConfigurationTalesExtension(ContextRequestViewAdapter): + """extension:back_configuration TALES expression""" + + def render(self, context=None): + if context is None: + context = self.context + manager = get_parent(context, IConfigurationManager) + if manager is not None: + return IBackOfficeConfiguration(manager) + + +@adapter_config(name='back-configuration', context=IConfigurationManager, provides=ITraversable) +class BackOfficeConfigurationTraverser(ContextAdapter): + """++back-configuration++ namespace traverser""" + + def traverse(self, name, furtherpath=None): + return IBackOfficeConfiguration(self.context) + + +@view_config(name='back-favicon.ico', context=IConfigurationManager) +def back_office_site_icon(request): + configuration = IBackOfficeConfiguration(request.context) + if configuration.icon is not None: + request = request.copy() + request.context = configuration.icon + return MediaFileView(request) + return HTTPNotFound()