src/pyams_content/component/illustration/__init__.py
changeset 140 67bad9f880ee
parent 0 7c0001cacf8e
child 206 90e3fa165ce1
--- a/src/pyams_content/component/illustration/__init__.py	Mon Sep 11 14:53:15 2017 +0200
+++ b/src/pyams_content/component/illustration/__init__.py	Mon Sep 11 14:54:30 2017 +0200
@@ -16,5 +16,125 @@
 # import standard library
 
 # import interfaces
+from pyams_content.component.illustration.interfaces import IIllustrationRenderer, IIllustration, IIllustrationTarget, \
+    ILLUSTRATION_KEY
+from pyams_file.interfaces import DELETED_FILE, IResponsiveImage, IFileInfo
+from pyams_i18n.interfaces import INegotiator, II18n
+from zope.annotation.interfaces import IAnnotations
+from zope.lifecycleevent.interfaces import IObjectAddedEvent, IObjectModifiedEvent
+from zope.location.interfaces import ISublocations
+from zope.traversing.interfaces import ITraversable
 
 # import packages
+from persistent import Persistent
+from pyams_i18n.property import I18nFileProperty
+from pyams_utils.adapter import adapter_config, ContextAdapter
+from pyams_utils.registry import query_utility
+from pyams_utils.request import check_request
+from pyams_utils.vocabulary import vocabulary_config
+from pyramid.events import subscriber
+from pyramid.threadlocal import get_current_registry
+from zope.container.contained import Contained
+from zope.interface import implementer, alsoProvides
+from zope.lifecycleevent import ObjectCreatedEvent, ObjectAddedEvent
+from zope.location import locate
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+
+
+@implementer(IIllustration)
+class Illustration(Persistent, Contained):
+    """Illustration persistent class"""
+
+    title = FieldProperty(IIllustration['title'])
+    alt_title = FieldProperty(IIllustration['alt_title'])
+    description = FieldProperty(IIllustration['description'])
+    author = FieldProperty(IIllustration['author'])
+    _data = I18nFileProperty(IIllustration['data'])
+    renderer = FieldProperty(IIllustration['renderer'])
+
+    @property
+    def data(self):
+        return self._data
+
+    @data.setter
+    def data(self, value):
+        self._data = value
+        for data in value.values():
+            if (data is not None) and (data is not DELETED_FILE):
+                alsoProvides(data, IResponsiveImage)
+
+
+@adapter_config(context=IIllustrationTarget, provides=IIllustration)
+def illustration_factory(context):
+    """Illustration factory"""
+    annotations = IAnnotations(context)
+    illustration = annotations.get(ILLUSTRATION_KEY)
+    if illustration is None:
+        illustration = annotations[ILLUSTRATION_KEY] = Illustration()
+        registry = get_current_registry()
+        registry.notify(ObjectCreatedEvent(illustration))
+        locate(illustration, context, '++illustration++')
+        registry.notify(ObjectAddedEvent(illustration, context, '++illustration++'))
+    return illustration
+
+
+def update_illustration_properties(illustration):
+    """Update missing file properties"""
+    request = check_request()
+    i18n = query_utility(INegotiator)
+    if i18n is not None:
+        lang = i18n.server_language
+        data = II18n(illustration).get_attribute('data', lang, request)
+        if data:
+            info = IFileInfo(data)
+            info.title = II18n(illustration).get_attribute('title', lang, request)
+            info.description = II18n(illustration).get_attribute('alt_title', lang, request)
+        for lang, data in (illustration.data or {}).items():
+            if data is not None:
+                IFileInfo(data).language = lang
+
+
+@subscriber(IObjectAddedEvent, context_selector=IIllustration)
+def handle_added_illustration(event):
+    """Handle added illustration"""
+    illustration = event.object
+    update_illustration_properties(illustration)
+
+
+@subscriber(IObjectModifiedEvent, context_selector=IIllustration)
+def handle_modified_illustration(event):
+    """Handle modified illustration"""
+    illustration = event.object
+    update_illustration_properties(illustration)
+
+
+@adapter_config(name='illustration', context=IIllustrationTarget, provides=ITraversable)
+class IllustrationNamespace(ContextAdapter):
+    """++illustration++ namespace adapter"""
+
+    def traverse(self, name, furtherpath=None):
+        return IIllustration(self.context)
+
+
+@adapter_config(name='illustration', context=IIllustrationTarget, provides=ISublocations)
+class IllustrationSublocations(ContextAdapter):
+    """Illustration sub-locations adapter"""
+
+    def sublocations(self):
+        return IIllustration(self.context),
+
+
+@vocabulary_config(name='PyAMS illustration renderers')
+class IllustrationRendererVocabulary(SimpleVocabulary):
+    """Illustration renderer utilities vocabulary"""
+
+    def __init__(self, context=None):
+        request = check_request()
+        translate = request.localizer.translate
+        registry = request.registry
+        context = Illustration()
+        terms = [SimpleTerm(name, title=translate(adapter.label))
+                 for name, adapter in sorted(registry.getAdapters((context, request), IIllustrationRenderer),
+                                             key=lambda x: x[1].weight)]
+        super(IllustrationRendererVocabulary, self).__init__(terms)